回精華區
作者amaki.bbs@luna.twbbs.org (巧克力羊) 看板: plan
標題[功能]看板精華區排行榜
時間月下夜想 (2004/01/02 Fri 22:58:57) Updated: 2004/01/02
  聽說不少站台有這東西,寫寫當新年禮物吧。

  站長先在Announce裡新增資料,檔名為@-topgem

  util/下新增這支topgemsize.c

  crontab -e設個定期跑的時間就可以了。

  另外這支程式裡有個node(),裡面的4094跟1024個別是我的硬碟初始化時的block跟

  fragment大小,這只能算出比較接近的inode數(一個inode佔去128 bytes),如果你的

  比例不是4096 / 1024請調整成自己硬碟的參數。

: src/util/Makefile

EXE =   ... topgemsize

: topgemsize.c

/*-------------------------------------------------------*/
/* util/topgemsize.c    ( NTHU CS MapleBBS Ver 3.10 )    */
/*-------------------------------------------------------*/
/* target : 看板精華區區排行榜                           */
/* create : 04/01/02                                     */
/* author : amaki.bbs@luna.twbbs.org                     */
/*-------------------------------------------------------*/


#include "bbs.h"

#define TOPGEM  "gem/@/@-topgem"

typedef struct
{
  int year;
  int yday;
  int mon;
  int mday;
  int wday;
  int hour;
} DATE;


typedef struct
{
  int bno;
  int dir_nums;
  int file_nums;
  int gsize;
} BGEM;


static BCACHE *bshm;
static BGEM *bgem;


static int
node(size)
  int size;
{
  int node, frag;

  node = (size / 4096) * 128;
  node += (frag = (size % 4096) / 1024) ? frag * 128 : 0;

  return node;
}


static void
gem_folder(folder, gem_set)
  char *folder;
  BGEM *gem_set;
{
  int fd, count, dnum;
  char fpath[64];
  HDR *xt, *hdr;
  struct stat st;

  if ((fd = open(folder, O_RDONLY)) < 0)
    return;

  fstat(fd, &st);
  hdr = xt = (HDR *) malloc(count = st.st_size);
  count = read(fd, xt, count) / sizeof(HDR);
  close(fd);

  do
  {
    hdr_fpath(fpath, folder, hdr);

    if (hdr->xmode & GEM_FOLDER)
    {
      gem_set->dir_nums++;
      if (dnum = rec_num(fpath, sizeof(HDR)) > 0)
      {
        gem_set->file_nums++;
        gem_set->gsize += dnum * sizeof(HDR) + node(dnum * sizeof(HDR));
        gem_folder(fpath, gem_set);
      }
    }
    else if (dashf(fpath))
    {
      stat(fpath, &st);
      gem_set->file_nums++;
      gem_set->gsize += st.st_size + node(st.st_size);
    }
  } while (++hdr < xt + count);

  free(xt);
}


static void
gem_counter(brd, gem_set)
  BRD *brd;
  BGEM *gem_set;
{
  int fd, count, dnum;
  char fpath[64], folder[64];
  HDR *xt, *hdr;
  struct stat st;

  sprintf(folder, "gem/brd/%s/%s", brd->brdname, FN_DIR);

  if ((fd = open(folder, O_RDONLY)) < 0)
    return;

  fstat(fd, &st);
  hdr = xt = (HDR *) malloc(count = st.st_size);
  count = read(fd, xt, count) / sizeof(HDR);
  close(fd);

  do
  {
    hdr_fpath(fpath, folder, hdr);

    if (hdr->xmode & GEM_FOLDER)
    {
      gem_set->dir_nums++;
      if (dnum = rec_num(fpath, sizeof(HDR)) > 0)
      {
        gem_set->file_nums++;
        gem_set->gsize += dnum * sizeof(HDR) + node(dnum * sizeof(HDR));
        gem_folder(fpath, gem_set);
      }
    }
    else if (dashf(fpath))
    {
      stat(fpath, &st);
      gem_set->file_nums++;
      gem_set->gsize += st.st_size + node(st.st_size);
    }
  } while (++hdr < xt + count);

  free(xt);
}


static void
gem_record(date)
  DATE *date;
{
  int ansi, i = 0;
  BRD *brd;
  BGEM *bgem_set;
  FILE *fp;
  char msg[80], dbuf[16], anony[16];

  if (!(fp = fopen(TOPGEM, "w")))
    return;

  sprintf(msg, "%d月%d日看板精華區排行", date->mon, date->mday);

  fprintf(fp, "\033[1;35;47m%*s%*s",
    41 + strlen(msg) / 2, msg, 41 - strlen(msg) / 2, "\033[m\n");
 fprintf(fp, "\033[1;37;45m【排  名】  【看    板】  【檔案數】  【目錄數】"
   "  【總精華區大小(bytes)】     \033[m\n");

  do
  {
    ansi = 0;
    bgem_set = bgem + i;
    brd = bshm->bcache + bgem_set->bno;
    sprintf(dbuf, "%d.", i + 1);
    sprintf(anony, "%c%s", brd->brdname[0], "○○○○");

    if (i < 5)
    {
      fprintf(fp, "  \033[1m%-11s%-14s%-12d%-12d%-d ", dbuf,
      (brd->battr & BRD_NOSTAT) ? anony : brd->brdname,
      bgem_set->file_nums, bgem_set->dir_nums, bgem_set->gsize);
      ansi = 1;
    }
    else if (i < 9)
    {
      fprintf(fp, "  \033[1;33m%-11s%-14s%-12d%-12d%-d ", dbuf,
      (brd->battr & BRD_NOSTAT) ? anony : brd->brdname,
      bgem_set->file_nums, bgem_set->dir_nums, bgem_set->gsize);
      ansi = 1;
    }
    else
    {
      fprintf(fp, "  %-11s%-14s%-12d%-12d%-d ", dbuf,
      (brd->battr & BRD_NOSTAT) ? anony : brd->brdname,
      bgem_set->file_nums, bgem_set->dir_nums, bgem_set->gsize);
    }

    if (bgem_set->gsize > 1048576)
      fprintf(fp, "(%dMB)%s\n", bgem_set->gsize / 1048576, ansi ? "\033[m":"");
    else if (bgem_set->gsize > 1024)
      fprintf(fp, "(%dKB)%s\n", bgem_set->gsize / 1024, ansi ? "\033[m" : "");
    else
      fprintf(fp, ansi ? "\033[m\n" : "\n");
  } while (++i < bshm->number);

  fclose(fp);
}


static int
bgem_cmp(a, b)
  BGEM *a, *b;
{
  return b->gsize - a->gsize;
}


int
main()
{
  int i;
  BRD *brd;
  DATE now;
  BGEM *gem_set;
  time_t time_now;
  struct tm *t;

  chdir(BBSHOME);

  bshm = shm_new(BRDSHM_KEY, sizeof(BCACHE));
  bgem = (BGEM *) malloc(sizeof(BGEM) * bshm->number);
  memset(bgem, 0, sizeof(BGEM) * bshm->number);

  time(&time_now);
  time_now -= 400;
  t = localtime(&time_now);
  now.year = t->tm_year;
  now.yday = t->tm_yday;
  now.mon = t->tm_mon + 1;
  now.mday = t->tm_mday;
  now.wday = t->tm_wday;
  now.hour = t->tm_hour;

  for (i = 0; i < bshm->number; i++)
  {
    brd = bshm->bcache + i;
    gem_set = bgem + i;
    /* amaki.030730: 開啟看板目錄下的bdata */
    if (*brd->brdname)
    {
      gem_set->bno = i;
      gem_counter(brd, gem_set);
    }
  }

  qsort(bgem, bshm->number, sizeof(BGEM), bgem_cmp);

  gem_record(&now);

  free(bgem);
  return 0;
}

--
  Origin: luna.twbbs.org
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻