home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / space / part01 next >
Encoding:
Internet Message Format  |  1991-02-19  |  29.5 KB

  1. From: fmc@cnam.cnam.fr (Frederic Chauveau)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i007:  space - summarize file system usage, Part01/01
  4. Message-ID: <1991Feb19.194519.20703@sparky.IMD.Sterling.COM>
  5. Date: 19 Feb 91 19:45:19 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: b060c9ab 12269837 8b3692a7 e32a229d
  8.  
  9. Submitted-by: Frederic Chauveau <fmc@cnam.cnam.fr>
  10. Posting-number: Volume 17, Issue 7
  11. Archive-name: space/part01
  12.  
  13. space is a tool which create and update data-bases to watch how much and
  14. by whom disk space is used. It maintains a record of the used space on
  15. a per day / per users / per file-system basis.
  16.  
  17. Frederic Chauveau <fmc@cnam.cnam.fr>
  18.  
  19. ---- Cut Here and unpack ----
  20. #!/bin/sh
  21. # This is space, a shell archive (shar 3.32)
  22. # made 02/13/1991 11:50 UTC by fmc@cnam.cnam.fr
  23. # Source directory /users/labinf/fmc/tools/Space
  24. #
  25. # existing files will NOT be overwritten
  26. #
  27. # This shar contains:
  28. # length  mode       name
  29. # ------ ---------- ------------------------------------------
  30. #   9367 -rw-r--r-- space.c
  31. #   4960 -rw-r--r-- sysdep.c
  32. #   1649 -rw-r--r-- defs.h
  33. #   3102 -rw-r--r-- Makefile
  34. #   1534 -r--r--r-- space.8
  35. #   4037 -rw-r--r-- INSTALL
  36. #
  37. if touch 2>&1 | fgrep 'amc' > /dev/null
  38.  then TOUCH=touch
  39.  else TOUCH=true
  40. fi
  41. # ============= space.c ==============
  42. if test X"$1" != X"-c" -a -f 'space.c'; then
  43.     echo "File already exists: skipping 'space.c'"
  44. else
  45. echo "x - extracting space.c (Text)"
  46. sed 's/^X//' << 'SHAR_EOF' > space.c &&
  47. X/*
  48. X * space    A tool to look out for greedy users
  49. X * $Header: /users/labinf/fmc/tools/Space/RCS/space.c,v 2.4 91/01/24 15:14:18 fmc Exp $
  50. X * $Source: /users/labinf/fmc/tools/Space/RCS/space.c,v $
  51. X * $Locker:  $
  52. X * $State: Exp $
  53. X * $Log:    space.c,v $
  54. X * Revision 2.4  91/01/24  15:14:18  fmc
  55. X * Split System dependencies.
  56. X * Fixed a bug in -tx options.
  57. X * 
  58. X * Revision 2.3  90/10/13  15:20:38  fmc
  59. X * Fixed a bug with the -D option (sort by Delta-percentage)
  60. X * Added a Startday compilation option.
  61. X * Some mode (final?) cleanup.
  62. X * 
  63. X * Revision 2.2  90/09/01  11:06:13  fmc
  64. X * added -d and -D option to sort user by delta or percentage
  65. X * Some more (final) clean-up.
  66. X * 
  67. X * Revision 2.1  90/08/30  19:00:36  fmc
  68. X * Do not log users occupying no space. Added -t option
  69. X * to look through all file Systems.
  70. X * 
  71. X * Revision 2.0  90/08/28  18:57:26  fmc
  72. X * Split the sums by file-systems. Some Clean Up
  73. X * 
  74. X * Revision 1.3  90/08/27  18:48:16  fmc
  75. X * Various Bug Fix
  76. X * 
  77. X * Revision 1.2  90/08/10  16:35:22  fmc
  78. X * Added -Ln option to have a sorted list with the last n days disk occupation.
  79. X * 
  80. X * Revision 1.1  90/08/02  13:47:16  fmc
  81. X * Initial revision
  82. X * 
  83. X * 
  84. X */
  85. X
  86. X#include "defs.h"
  87. X
  88. Xstatic char SortFlag = 0;
  89. Xstatic char DataFile[128];
  90. Xstatic RecP *Sorted;
  91. Xstatic short StartDay = STARTDAY;
  92. X
  93. Xint SortAllRecs(r1, r2)
  94. XSuprecP *r1, *r2; {
  95. X  long v1, v2; 
  96. X
  97. X  switch (SortFlag) 
  98. X    {
  99. X    case TMAX: v1 = (*r1)->Fmax; v2 = (*r2)->Fmax; break;
  100. X    case TMIN: v1 = (*r1)->Fmin; v2 = (*r2)->Fmin; break;
  101. X    case CUR: v1 = (*r1)->Fcur; v2 = (*r2)->Fcur; break;
  102. X    }
  103. X  if (v1 == v2)
  104. X    return 0;
  105. X  return (v2 > v1) ? 1 : -1;
  106. X}
  107. X
  108. Xint SortUsers(r1, r2)
  109. XRecP *r1, *r2; {
  110. X  long v1, v2;
  111. X  v1 = (*r1)->blocks[CurrentDay];
  112. X  v2 = (*r2)->blocks[CurrentDay];
  113. X
  114. X  if (v1 == v2)
  115. X    return 0;
  116. X  return (v2 > v1) ? 1 : -1;
  117. X}
  118. X
  119. Xvoid GetRecords(fn)
  120. Xchar *fn; {
  121. X  unsigned int fd, i, j;
  122. X  Record tmp;
  123. X
  124. X  sprintf(DataFile,"%s/space-%s.dat",DATADIR,fn);
  125. X  fd = open(DataFile,0);
  126. X  if (fd < 0) {
  127. X    perror(DataFile);
  128. X    if (log_file && (log_file != stderr))
  129. X      fclose(log_file);
  130. X    exit(1);
  131. X  }
  132. X
  133. X  for (i = 0; i != MAXUSERS; i++)
  134. X    if (WhatDidTheyDo[i]) {
  135. X      free(WhatDidTheyDo[i]);
  136. X      WhatDidTheyDo[i] = NULL;
  137. X    }
  138. X  while (read(fd, &tmp, sizeof(Record)) == sizeof(Record)) {
  139. X    register unsigned long max = 0L, min = 500000L;
  140. X    if (WhatDidTheyDo[tmp.uid])
  141. X      fprintf(log_file,"Duplicate Record Entry for Uid %d\n",tmp.uid);
  142. X    for (i = 0; i <= CurrentDay; i++) {
  143. X      if (tmp.blocks[i] && (tmp.blocks[i] < min))
  144. X    min = tmp.blocks[i];
  145. X      if (tmp.blocks[i] > max) {
  146. X    max = tmp.blocks[i];
  147. X      }
  148. X    }
  149. X    tmp.dmax = max;
  150. X    tmp.dmin = min;
  151. X    WhatDidTheyDo[tmp.uid] = (RecP) malloc(sizeof(Record));
  152. X    *(WhatDidTheyDo[tmp.uid]) = tmp;
  153. X    MaxUsers++;
  154. X  }
  155. X  close(fd);
  156. X}
  157. X
  158. Xvoid SaveRecords(fn)
  159. Xchar *fn; {
  160. X  unsigned int fd, i;
  161. X
  162. X  sprintf(DataFile,"%s/space-%s.dat",DATADIR,fn);
  163. X  close(creat(DataFile,0777));
  164. X  fd = open(DataFile,1);
  165. X  if (fd < 0) {
  166. X    perror(DataFile);
  167. X    if (log_file && (log_file != stderr))
  168. X      fclose(log_file);
  169. X    exit(1);
  170. X  }
  171. X
  172. X  for (i = 0; i != MAXUSERS; i++)
  173. X    if (WhatDidTheyDo[i] && WhatDidTheyDo[i]->dmax)
  174. X      write(fd, WhatDidTheyDo[i], sizeof(Record));
  175. X  close(fd);
  176. X}
  177. X
  178. Xvoid DispAllFs() {
  179. X  register int i, j;
  180. X
  181. X  printf("  User   ");
  182. X  for (i = 0; i!= MaxFs; i++)
  183. X    printf("%7s",all_fs[i].dev);
  184. X  puts("  Total");
  185. X  for (i = 0; i != MaxAllUsers; i++) {
  186. X    printf("%9s",AllRecs[i]->name);
  187. X    for (j = 0; j != MaxFs; j++) {
  188. X      unsigned long v;
  189. X      v = (SortFlag == CUR) ? AllRecs[i]->current[j] :
  190. X    (SortFlag == TMIN) ? AllRecs[i]->min[j] : AllRecs[i]->max[j];
  191. X      printf("%7lu",v);
  192. X    }
  193. X    printf("%7lu\n",(SortFlag == CUR) ? AllRecs[i]->Fcur :
  194. X    (SortFlag == TMIN) ? AllRecs[i]->Fmin : AllRecs[i]->Fmax);
  195. X  }
  196. X}
  197. X
  198. X
  199. Xvoid LookRoom(fs)
  200. X{
  201. X  char dev[80];
  202. X  register int i;
  203. X  
  204. X  sprintf(dev, "/dev/r%s", fs);
  205. X  fprintf(log_file,"Checking %s\n",dev);
  206. X  check(dev);
  207. X  for (i = 0; i != MAXUSERS; i++) {
  208. X    unsigned long j;
  209. X
  210. X    if (!WhatDidTheyDo[i])
  211. X      continue;
  212. X    j = WhatDidTheyDo[i]->blocks[CurrentDay];
  213. X    WhatDidTheyDo[i]->current = j;
  214. X    if (WhatDidTheyDo[i]->dmin > j)
  215. X      WhatDidTheyDo[i]->dmin = j;
  216. X    else if (WhatDidTheyDo[i]->dmax < j)
  217. X      WhatDidTheyDo[i]->dmax = j;
  218. X  }
  219. X}
  220. X
  221. Xint SortDelta(r1, r2)
  222. XRecP *r1, *r2; {
  223. X  long v1, v2;
  224. X  v1 = (*r1)->ddel;
  225. X  v2 = (*r2)->ddel;
  226. X
  227. X  if (v1 == v2)
  228. X    return 0;
  229. X  return (v2 > v1) ? 1 : -1;
  230. X}
  231. X
  232. Xint SortPerc(r1, r2)
  233. XRecP *r1, *r2; {
  234. X  double v1, v2;
  235. X  v1 = (*r1)->dper;
  236. X  v2 = (*r2)->dper;
  237. X
  238. X  if (v1 == v2)
  239. X    return 0;
  240. X  return (v2 > v1) ? 1 : -1;
  241. X}
  242. X
  243. Xvoid LookDelta(min,mode) {
  244. X  register int i, j;
  245. X
  246. X  if (min > CurrentDay) {
  247. X    fprintf(log_file,"Cannot look more than %d days in the past\n",CurrentDay);
  248. X    min=CurrentDay;
  249. X  }
  250. X  Sorted = (RecP *) malloc(MaxUsers * sizeof(RecP));
  251. X  for (i = 0, j = 0; i != MAXUSERS; i++)
  252. X    if (WhatDidTheyDo[i]) {
  253. X      double f;
  254. X      Sorted[j] = WhatDidTheyDo[i];
  255. X      Sorted[j]->ddel = Sorted[j]->current - Sorted[j]->blocks[CurrentDay-min];
  256. X      f = (double) Sorted[j]->blocks[CurrentDay-min];
  257. X      if (f)
  258. X    Sorted[j]->dper = (double) Sorted[j]->current / f;
  259. X      else
  260. X    Sorted[j]->dper = HUGE;
  261. X      j++;
  262. X    }
  263. X  qsort(Sorted, MaxUsers, sizeof(RecP), (mode) ? SortDelta : SortPerc);
  264. X  for (i = 0; i != MaxUsers; i++) {
  265. X    if (!Sorted[i]->ddel)
  266. X      continue;
  267. X    printf("%8s\t%10lu\t%10lu",Sorted[i]->name,Sorted[i]->current,
  268. X       Sorted[i]->blocks[CurrentDay-min]);
  269. X    if (mode) 
  270. X      printf("\t%10ld\n",Sorted[i]->ddel);
  271. X    else if (Sorted[i]->dper != HUGE)
  272. X      printf("\t%10.6f%%\n",(Sorted[i]->dper - 1)*100);
  273. X    else
  274. X      printf("\t+ Infini \n");
  275. X  }
  276. X}
  277. X
  278. XInitWDTD() {
  279. X  register short i;
  280. X  FILE *pwd = fopen("/etc/passwd","r");
  281. X  char buf[BUFSIZ], *p, *strchr();
  282. X  int uid;
  283. X  
  284. X  while (fgets(buf,BUFSIZ,pwd)) {
  285. X    if (!*buf || (*buf == '#'))
  286. X      continue;
  287. X    p = strchr(buf,':');
  288. X    if (!p || !*p)
  289. X      continue;
  290. X    *p = '\0';
  291. X    p = strchr(p+1,':');
  292. X    uid = atoi(p+1);
  293. X    if (uid < 0)
  294. X      fprintf(log_file,"Skipping negative uid %d (%s)\n",uid,buf);
  295. X    else if (WhatDidTheyDo[uid])
  296. X      fprintf(log_file,"Duplicate entry uid %d (%s %s)\n",uid,buf,
  297. X          WhatDidTheyDo[uid]->name);
  298. X    else {
  299. X      WhatDidTheyDo[uid] = (RecP) malloc(sizeof(Record));
  300. X      strncpy(WhatDidTheyDo[uid]->name,buf,8);
  301. X      WhatDidTheyDo[uid]->uid = uid;
  302. X      for (i = 0; i != TOKEEP; i++) {
  303. X    WhatDidTheyDo[uid]->blocks[i] = 0L;
  304. X      }
  305. X      MaxUsers++;
  306. X    }
  307. X  }
  308. X  fclose(pwd);
  309. X}
  310. X
  311. Xvoid ShowUser(username)
  312. Xchar *username; {
  313. X  long first = 0L, min = 0L, max = 0L;
  314. X  register int uid, i, j, k;
  315. X  Record *r;
  316. X
  317. X  uid = usertouid(username);
  318. X  r = WhatDidTheyDo[uid];
  319. X  if (!r) {
  320. X    fprintf(stderr, "No user %s [%d] on the device\n",username,uid);
  321. X    return;
  322. X  }
  323. X  for (i = 0; i <= CurrentDay; i++) {
  324. X    if (!r->blocks[i])
  325. X      continue;
  326. X    if (!first) {
  327. X      first = r->blocks[i];
  328. X      break;
  329. X    }
  330. X  }
  331. X  printf("User %s (%d) is between %lu and %lu blocks (beginning at %lu)\n",
  332. X     r->name, r->uid, r->dmin, r->dmax, first);
  333. X  if (CurrentDay > 32)
  334. X    k = 32;
  335. X  else
  336. X    k = CurrentDay;
  337. X  printf("Here are the last %d days :",k);
  338. X  for (j = 0, i = CurrentDay - k; i != CurrentDay; i++, j++)
  339. X    if (j & 07)
  340. X      printf("%8lu ",r->blocks[i+1]);
  341. X    else 
  342. X      printf("\n%8lu ",r->blocks[i+1]);
  343. X  puts("");
  344. X}
  345. X
  346. Xint CurDay() {
  347. X  time_t t;
  348. X  struct tm *tt;
  349. X
  350. X  t = time((time_t *) 0);
  351. X  tt = localtime(&t);
  352. X  return (tt->tm_yday - StartDay);
  353. X}
  354. X
  355. XShowList(n) {
  356. X  register int i, j;
  357. X
  358. X  Sorted = (RecP *) malloc(MaxUsers * sizeof(RecP));
  359. X  for (i = 0, j = 0; i != MAXUSERS; i++)
  360. X    if (WhatDidTheyDo[i])
  361. X      Sorted[j++] = WhatDidTheyDo[i];
  362. X  qsort(Sorted, MaxUsers, sizeof(RecP), SortUsers);
  363. X  if (n > CurrentDay)
  364. X    n = CurrentDay;
  365. X  for (i = 0; i != MaxUsers; i++) {
  366. X    printf("%8s",Sorted[i]->name);
  367. X    for (j = 0; j <= n; j++)
  368. X      printf("%8lu",Sorted[i]->blocks[CurrentDay-j]);
  369. X    puts("");
  370. X  }
  371. X}
  372. X
  373. Xvoid Usage() {
  374. X  fprintf(stderr,"Usage: space -iul device\n");
  375. X  fprintf(stderr,"   or  space -Ldays device\n");
  376. X  fprintf(stderr,"   or  space -s device user1 user2 ...\n");
  377. X  fprintf(stderr,"   or  space -t[cm-M]\n");
  378. X  fprintf(stderr,"   or  space -[dD]days device\n");
  379. X  if (log_file && log_file != stderr) {
  380. X    fclose(log_file);
  381. X  }
  382. X  exit(1);
  383. X}
  384. X
  385. Xmain(argc,argv)
  386. Xchar **argv; {
  387. X  char *fs;
  388. X  ++argv; --argc;
  389. X  log_file = fopen(LOGFILE,"a");
  390. X  if (!log_file) {
  391. X    perror(LOGFILE);
  392. X    log_file = stderr;
  393. X    fprintf(stderr,"Loggin informations on stderr\n");
  394. X  }
  395. X  if (argc && (**argv == '-')) {
  396. X    CurrentDay = CurDay();
  397. X    switch(argv[0][1]) {
  398. X      case 'i':
  399. X    InitWDTD(); 
  400. X    LookRoom(argv[1]); 
  401. X    SaveRecords(argv[1]);
  402. X    exit();
  403. X      case 'u':
  404. X    GetRecords(argv[1]); 
  405. X    LookRoom(argv[1]); 
  406. X    SaveRecords(argv[1]);
  407. X    break;
  408. X      case 's':
  409. X    GetRecords(argv[1]);
  410. X    ++argv; --argc;
  411. X    while (++argv, --argc)
  412. X      ShowUser(*argv);
  413. X    break;
  414. X      case 'l':
  415. X    GetRecords(argv[1]);
  416. X    ShowList(0);
  417. X    break;
  418. X      case 'L':
  419. X    GetRecords(argv[1]);
  420. X    ShowList(atoi(*argv+2));
  421. X    break;
  422. X      case 'd':
  423. X      case 'D':
  424. X    GetRecords(argv[1]);
  425. X    LookDelta(atoi(*argv + 2),argv[0][1] == 'd');
  426. X    break;
  427. X      case 't':
  428. X    if (!argv[0][2] || argv[0][2] == 'c')
  429. X      SortFlag = CUR;
  430. X    else if (argv[0][2] == 'm' || argv[0][2] == '-')
  431. X      SortFlag = TMIN;
  432. X    else
  433. X      SortFlag = TMAX;
  434. X    AllFileSystems(CurrentDay);
  435. X    break;
  436. X      default:
  437. X    Usage();
  438. X      }
  439. X  }
  440. X  else
  441. X    Usage();
  442. X  if (log_file && log_file != stderr)
  443. X    fclose(log_file);
  444. X}
  445. SHAR_EOF
  446. $TOUCH -am 0124154791 space.c &&
  447. chmod 0644 space.c ||
  448. echo "restore of space.c failed"
  449. set `wc -c space.c`;Wc_c=$1
  450. if test "$Wc_c" != "9367"; then
  451.     echo original size 9367, current size $Wc_c
  452. fi
  453. fi
  454. # ============= sysdep.c ==============
  455. if test X"$1" != X"-c" -a -f 'sysdep.c'; then
  456.     echo "File already exists: skipping 'sysdep.c'"
  457. else
  458. echo "x - extracting sysdep.c (Text)"
  459. sed 's/^X//' << 'SHAR_EOF' > sysdep.c &&
  460. X/*
  461. X * space    A tool to look out for greedy users
  462. X * $Header: /users/labinf/fmc/tools/Space/RCS/sysdep.c,v 1.2 91/01/24 15:30:13 fmc Exp $
  463. X * $Source: /users/labinf/fmc/tools/Space/RCS/sysdep.c,v $
  464. X * $Locker:  $
  465. X * $State: Exp $
  466. X * $Log:    sysdep.c,v $
  467. X * Revision 1.2  91/01/24  15:30:13  fmc
  468. X * Added FSNAME define to check for non-local file-systems.
  469. X * 
  470. X * Revision 1.1  91/01/24  15:17:50  fmc
  471. X * Initial revision
  472. X * 
  473. X */
  474. X
  475. X#include "defs.h"
  476. X
  477. XRecP WhatDidTheyDo[MAXUSERS];
  478. XSuprecP TempRecs[MAXUSERS];
  479. XSuprecP *AllRecs;
  480. Xint MaxUsers = 0, MaxAllUsers = 0;
  481. XFsName all_fs[MAXFS];
  482. Xint MaxFs = 0;
  483. X
  484. XFILE *log_file;
  485. Xshort CurrentDay;
  486. X
  487. X/*
  488. X * User name to UID.
  489. X */
  490. X
  491. Xint usertouid(user)
  492. Xchar *user;
  493. X{
  494. X  register struct passwd *pw;
  495. X  struct passwd *getpwent();
  496. X  
  497. X  setpwent();
  498. X  while (pw = getpwent()) 
  499. X    {
  500. X      if (!strcmp(user,pw->pw_name)) {
  501. X    endpwent();      
  502. X    return (pw->pw_uid);
  503. X      }
  504. X    }
  505. X  endpwent();
  506. X  return -1;
  507. X}
  508. X
  509. X/*
  510. X * UID to user name
  511. X */
  512. X
  513. Xchar *uidtouser(uid)
  514. Xshort uid;
  515. X{
  516. X  register struct passwd *pw;
  517. X  struct passwd *getpwent();
  518. X  
  519. X  setpwent();
  520. X  while (pw = getpwent()) 
  521. X    {
  522. X      if (uid == pw->pw_uid) {
  523. X    endpwent();      
  524. X    return (pw->pw_name);
  525. X      }
  526. X    }
  527. X  endpwent();
  528. X  return NULL;
  529. X}
  530. X
  531. X/*
  532. X * Take inode ino/ip into account. ino (the current inode number) is used only
  533. X * to log inodes which belongs to no known users.
  534. X */
  535. X
  536. Xvoid acct(ip,ino)
  537. Xregister struct dinode *ip;
  538. Xint ino;
  539. X{
  540. X  int uid = ip->di_uid;
  541. X
  542. X  if ((ip->di_mode & IFMT) == 0)
  543. X    return;
  544. X  if ((uid >= 0) && (uid < MAXUSERS)) {
  545. X    if (!WhatDidTheyDo[uid]) {
  546. X      register int i;
  547. X      char *n;
  548. X      WhatDidTheyDo[uid] = (RecP) malloc(sizeof(Record));
  549. X      WhatDidTheyDo[uid]->uid = uid;
  550. X      n = uidtouser(uid);
  551. X      if (n)
  552. X    strcpy(WhatDidTheyDo[uid]->name,n);
  553. X      else
  554. X    sprintf(WhatDidTheyDo[uid]->name,"#%d",uid);
  555. X      for (i = 0; i != CurrentDay; i++)
  556. X    WhatDidTheyDo[uid]->blocks[i] = 0L;
  557. X      MaxUsers++;
  558. X    }
  559. X    WhatDidTheyDo[uid]->blocks[CurrentDay] += ip->di_blocks / 2;
  560. X    if (WhatDidTheyDo[uid]->name[0] == '#')
  561. X      fprintf(log_file,"inode %d of %d blocks owned by unknown uid %d\n",
  562. X          ino,ip->di_blocks,uid);
  563. X  }
  564. X}
  565. X
  566. X/*
  567. X * Block Read. Read block bno of size cnt from file fd into buf.
  568. X */
  569. X
  570. Xvoid bread(fd, bno, buf, cnt)
  571. Xunsigned bno;
  572. Xchar *buf;
  573. X{
  574. X  
  575. X  lseek(fd, (long)bno * DEV_BSIZE, L_SET);
  576. X  if (read(fd, buf, cnt) != cnt) {
  577. X    fprintf(log_file, "\tread error at block %u\n", bno);
  578. X    if (log_file && log_file != stderr)
  579. X      fclose(log_file);
  580. X    exit(1);
  581. X  }
  582. X}
  583. X
  584. Xunion {
  585. X  struct fs u_sblock;
  586. X  char dummy[SBSIZE];
  587. X} sb_un;
  588. X#define sblock sb_un.u_sblock
  589. X
  590. Xstruct dinode itab[MAXBSIZE/sizeof(struct dinode)];
  591. Xunsigned    ino;
  592. X
  593. X/*
  594. X * Browse the file file_system. file should be the name of a block device
  595. X * corresponding to a disk partition.
  596. X */
  597. X
  598. Xvoid check(file)
  599. Xchar *file;
  600. X{
  601. X  register int i, j, nfiles;
  602. X  daddr_t iblk;
  603. X  int c, fd;
  604. X  
  605. X  fd = open(file, O_RDONLY);
  606. X  if (fd < 0) {
  607. X    fprintf(log_file, "\tCan't access %s\n",file);
  608. X    return;
  609. X  }
  610. X  sync();
  611. X  bread(fd, SBLOCK, (char *)&sblock, SBSIZE);
  612. X  nfiles = sblock.fs_ipg * sblock.fs_ncg;
  613. X  for (ino = 0; ino < nfiles; ) {
  614. X    iblk = fsbtodb(&sblock, itod(&sblock, ino));
  615. X    bread(fd, iblk, (char *)itab, sblock.fs_bsize);
  616. X    for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) {
  617. X      if (ino < ROOTINO)
  618. X    continue;
  619. X      acct(&itab[j],ino);
  620. X    }
  621. X  }
  622. X  close(fd);
  623. X}
  624. X
  625. X/*
  626. X * Browse though all file-systems (using getfsent()) and check all
  627. X * valid file system (file system of type ufs_name). 
  628. X */
  629. X
  630. Xvoid AllFileSystems(day)
  631. Xshort day;
  632. X{
  633. X  register struct fstab *fs;
  634. X  register char *cp;
  635. X  char dev[80], *rindex();
  636. X  FsName *fsp;
  637. X  register int i, j;
  638. X  
  639. X  if (setfsent() == 0) {
  640. X    fprintf(log_file, "space: no %s file\n", FSTAB);
  641. X    exit(1);
  642. X  }
  643. X  while (fs = getfsent()) {
  644. X
  645. X    /*
  646. X     * Make sure we can read the file system.
  647. X     */
  648. X
  649. X#ifdef FSNAME
  650. X    if (!strcmp(fs->fs_name,FSNAME))
  651. X      continue;
  652. X#endif
  653. X    if (strcmp(fs->fs_type, FSTAB_RO) &&
  654. X    strcmp(fs->fs_type, FSTAB_RW) &&
  655. X    strcmp(fs->fs_type, FSTAB_RQ))
  656. X      continue;
  657. X    cp = rindex(fs->fs_spec, '/');
  658. X    if (cp == 0)
  659. X      continue;
  660. X    fsp = all_fs + MaxFs;
  661. X    strcpy(fsp->dev,++cp);
  662. X    fsp->mount_point = (char *) malloc(strlen(fs->fs_file)+1);
  663. X    strcpy(fsp->mount_point,fs->fs_file);
  664. X    GetRecords(cp);
  665. X    for (i = 0; i != MAXUSERS; i++) {
  666. X      RecP rp = WhatDidTheyDo[i];
  667. X      SuprecP sp = TempRecs[i];
  668. X
  669. X      if (!rp) 
  670. X    continue;
  671. X      if (!sp) {
  672. X    sp = TempRecs[i] = (SuprecP) malloc(sizeof(Suprec));
  673. X    sp->uid = rp->uid;
  674. X    strcpy(sp->name,rp->name);
  675. X    MaxAllUsers++;
  676. X      }
  677. X      sp->Fcur += sp->current[MaxFs] = rp->current;
  678. X      sp->Fmin += sp->min[MaxFs] = rp->dmin;
  679. X      sp->Fmax += sp->max[MaxFs] = rp->dmax;
  680. X    }
  681. X    MaxFs++;
  682. X  }
  683. X  endfsent();
  684. X  AllRecs = (SuprecP *) malloc(MaxAllUsers * sizeof(SuprecP));
  685. X  for (i = 0, j = 0; i != MAXUSERS; i++)
  686. X    if (TempRecs[i])
  687. X      AllRecs[j++] = TempRecs[i];
  688. X  qsort(AllRecs,MaxAllUsers,sizeof(SuprecP),SortAllRecs);
  689. X  DispAllFs();
  690. X}
  691. X
  692. SHAR_EOF
  693. $TOUCH -am 0124154791 sysdep.c &&
  694. chmod 0644 sysdep.c ||
  695. echo "restore of sysdep.c failed"
  696. set `wc -c sysdep.c`;Wc_c=$1
  697. if test "$Wc_c" != "4960"; then
  698.     echo original size 4960, current size $Wc_c
  699. fi
  700. fi
  701. # ============= defs.h ==============
  702. if test X"$1" != X"-c" -a -f 'defs.h'; then
  703.     echo "File already exists: skipping 'defs.h'"
  704. else
  705. echo "x - extracting defs.h (Text)"
  706. sed 's/^X//' << 'SHAR_EOF' > defs.h &&
  707. X/*
  708. X * defs.h
  709. X * $Header:
  710. X * $Source:
  711. X * $Locker:  $
  712. X * $State: Exp $
  713. X * $Log:    
  714. X * 
  715. X */
  716. X
  717. X#include <stdio.h>
  718. X#include <sys/types.h>
  719. X#include <signal.h>
  720. X#include <ctype.h>
  721. X#include <pwd.h>
  722. X#include <fstab.h>
  723. X#include <math.h>
  724. X#include <sys/time.h>
  725. X#include <sys/stat.h>
  726. X#include <sys/param.h>
  727. X#include <sys/file.h>
  728. X#include <ufs/fs.h>
  729. X#ifdef ULTRIX
  730. X#include <sys/inode.h>
  731. X#else
  732. X#include <sys/vnode.h>
  733. X#include <ufs/inode.h>
  734. X#endif
  735. X
  736. X#ifndef TOKEEP
  737. X#define TOKEEP 365
  738. X#endif
  739. X
  740. X#define MAXUSERS 9999
  741. X#define MAXFS 10
  742. X
  743. X#define CUR    0
  744. X#define TMIN    1
  745. X#define TMAX    2
  746. X#define FCUR    3
  747. X#define FMIN    4
  748. X#define FMAX    5
  749. X
  750. Xtypedef unsigned long Blocks[TOKEEP];
  751. X
  752. Xtypedef struct {
  753. X  char dev[5];
  754. X  char *mount_point;
  755. X} FsName;  
  756. X
  757. Xtypedef struct {
  758. X  short uid;
  759. X  char name[9];
  760. X  unsigned long current[MAXFS], min[MAXFS], max[MAXFS];
  761. X  unsigned long Fcur, Fmin, Fmax;
  762. X} Suprec, *SuprecP;
  763. X
  764. Xtypedef struct {
  765. X  short uid;
  766. X  char name[9];
  767. X  unsigned long current;
  768. X  union {
  769. X    unsigned long min;
  770. X    long delta;
  771. X  } delt;
  772. X#define dmin delt.min
  773. X#define ddel delt.delta
  774. X  union {
  775. X    unsigned long max;
  776. X    double perc;
  777. X  } perc;
  778. X#define dmax perc.max
  779. X#define dper perc.perc
  780. X  Blocks blocks;
  781. X} Record, *RecP;
  782. X
  783. X
  784. X#ifndef DATADIR
  785. X#define DATADIR "/usr/tmp"
  786. X#endif
  787. X
  788. X#ifndef LOGFILE
  789. X#define LOGFILE "/usr/tmp/space.log"
  790. X#endif
  791. X
  792. X#ifndef STARTDAY
  793. X#define STARTDAY 0
  794. X#endif
  795. X
  796. Xextern FILE *log_file;
  797. Xextern short CurrentDay;
  798. Xextern short StartDay;
  799. Xextern char SortFlag;
  800. Xextern RecP WhatDidTheyDo[MAXUSERS];
  801. Xextern RecP *Sorted;
  802. Xextern SuprecP TempRecs[MAXUSERS];
  803. Xextern SuprecP *AllRecs;
  804. Xextern int MaxUsers, MaxAllUsers;
  805. Xextern FsName all_fs[MAXFS];
  806. Xextern int MaxFs;
  807. X
  808. Xint SortAllRecs();
  809. X
  810. SHAR_EOF
  811. $TOUCH -am 0124154791 defs.h &&
  812. chmod 0644 defs.h ||
  813. echo "restore of defs.h failed"
  814. set `wc -c defs.h`;Wc_c=$1
  815. if test "$Wc_c" != "1649"; then
  816.     echo original size 1649, current size $Wc_c
  817. fi
  818. fi
  819. # ============= Makefile ==============
  820. if test X"$1" != X"-c" -a -f 'Makefile'; then
  821.     echo "File already exists: skipping 'Makefile'"
  822. else
  823. echo "x - extracting Makefile (Text)"
  824. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  825. X# $Header:
  826. X# $Source:
  827. X# $Locker:  $
  828. X# $State: Exp $
  829. X# $Log:    Makefile,v $
  830. X# Revision 1.9  91/01/24  15:48:42  fmc
  831. X# More fixes.
  832. X# 
  833. X# Revision 1.7  91/01/24  15:28:46  fmc
  834. X# Added check for make depend.
  835. X# 
  836. X# Revision 1.6  91/01/24  15:16:42  fmc
  837. X# moved the system dependent stuff in sysdep.c
  838. X# 
  839. X# Revision 1.5  90/09/01  11:05:52  fmc
  840. X# Added install and clean target.
  841. X# 
  842. X# Revision 1.4  90/08/31  16:26:24  fmc
  843. X# Added makedepend
  844. X# 
  845. X# Revision 1.3  90/08/31  16:19:10  fmc
  846. X# More clean up
  847. X# 
  848. X# Revision 1.2  90/08/30  19:01:25  fmc
  849. X# Some cleanup
  850. X# 
  851. X# Revision 1.1  90/08/08  17:53:12  fmc
  852. X# Initial revision
  853. X#
  854. X
  855. XDESTDIR=/users/labinf/fmc/bin
  856. XCC=gcc
  857. XDEBUGFLAGS= -g
  858. XOPTFLAGS= -O -fwritable-strings -finline-functions
  859. XCPPFLAGS=
  860. X#
  861. X# For some system you have to define FSNAME as a string 
  862. X# with the type of local file-system. 
  863. X# On Ultrix it should be :
  864. X# SYSFLAGS= -DFSNAME=\"ufs\" -DULTRIX
  865. XSYSFLAGS= -DFSNAME=\"ufs\" -DULTRIX -DDATADIR=\"/usr/src\"
  866. XCFLAGS= $(DEBUGFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(SYSFLAGS)
  867. XLDFLAGS= $(DEBUGFLAGS)
  868. XMISC= Makefile space.8 INSTALL
  869. XSRCS= space.c sysdep.c defs.h
  870. XOBJS= space.o sysdep.o
  871. XMAKEDEPEND= makedepend
  872. X
  873. Xall:    space
  874. X
  875. Xspace: $(OBJS)
  876. X    $(CC) $(CFLAGS) $(LDFLAGS) -o space $(OBJS) -lm
  877. X
  878. Xinstall: all
  879. X    install space $(DESTDIR)
  880. X
  881. Xclean:
  882. X    rm -f *~ #* *.o core space .depend
  883. X
  884. Xdepend: $(SRCS)
  885. X    $(MAKEDEPEND) -- $(CPPFLAGS) $(SYSFLAGS) -- $(SRCS)
  886. X
  887. Xshar:    $(SRCS) $(MISC)
  888. X    shar -n space -a -x -c -o space.shar $(SRCS) $(MISC)
  889. X    
  890. X
  891. X# DO NOT DELETE THIS LINE -- make depend depends on it.
  892. X
  893. Xspace.o: defs.h /usr/include/stdio.h /usr/include/sys/types.h
  894. Xspace.o: /usr/include/signal.h /usr/include/ctype.h /usr/include/pwd.h
  895. Xspace.o: /usr/include/fstab.h /usr/local/lib/gcc-include/math.h
  896. Xspace.o: /usr/include/sys/time.h /usr/include/sys/stat.h
  897. Xspace.o: /usr/include/sys/param.h /usr/include/machine/param.h
  898. Xspace.o: /usr/include/sys/smp_lock.h /usr/include/sys/file.h
  899. Xspace.o: /usr/include/ufs/fs.h /usr/include/sys/inode.h
  900. Xspace.o: /usr/include/sys/gnode_common.h /usr/include/ufs/ufs_inode.h
  901. Xspace.o: /usr/include/sys/gnode.h
  902. Xsysdep.o: defs.h /usr/include/stdio.h /usr/include/sys/types.h
  903. Xsysdep.o: /usr/include/signal.h /usr/include/ctype.h /usr/include/pwd.h
  904. Xsysdep.o: /usr/include/fstab.h /usr/local/lib/gcc-include/math.h
  905. Xsysdep.o: /usr/include/sys/time.h /usr/include/sys/stat.h
  906. Xsysdep.o: /usr/include/sys/param.h /usr/include/machine/param.h
  907. Xsysdep.o: /usr/include/sys/smp_lock.h /usr/include/sys/file.h
  908. Xsysdep.o: /usr/include/ufs/fs.h /usr/include/sys/inode.h
  909. Xsysdep.o: /usr/include/sys/gnode_common.h /usr/include/ufs/ufs_inode.h
  910. Xsysdep.o: /usr/include/sys/gnode.h
  911. Xdefs.o: /usr/include/stdio.h /usr/include/sys/types.h /usr/include/signal.h
  912. Xdefs.o: /usr/include/ctype.h /usr/include/pwd.h /usr/include/fstab.h
  913. Xdefs.o: /usr/local/lib/gcc-include/math.h /usr/include/sys/time.h
  914. Xdefs.o: /usr/include/sys/stat.h /usr/include/sys/param.h
  915. Xdefs.o: /usr/include/machine/param.h /usr/include/sys/smp_lock.h
  916. Xdefs.o: /usr/include/sys/file.h /usr/include/ufs/fs.h
  917. Xdefs.o: /usr/include/sys/inode.h /usr/include/sys/gnode_common.h
  918. Xdefs.o: /usr/include/ufs/ufs_inode.h /usr/include/sys/gnode.h
  919. SHAR_EOF
  920. $TOUCH -am 0213114991 Makefile &&
  921. chmod 0644 Makefile ||
  922. echo "restore of Makefile failed"
  923. set `wc -c Makefile`;Wc_c=$1
  924. if test "$Wc_c" != "3102"; then
  925.     echo original size 3102, current size $Wc_c
  926. fi
  927. fi
  928. # ============= space.8 ==============
  929. if test X"$1" != X"-c" -a -f 'space.8'; then
  930.     echo "File already exists: skipping 'space.8'"
  931. else
  932. echo "x - extracting space.8 (Text)"
  933. sed 's/^X//' << 'SHAR_EOF' > space.8 &&
  934. X.\" RCSID: @(#)space.8    2.3    11/10/90
  935. X.TH space 8 
  936. X.SH Name
  937. Xspace \- summarize file system usage
  938. X.SH Syntax
  939. X.B /usr/local/bin/space
  940. X[ option ] ...
  941. X[ filesystem ]
  942. X.SH Description
  943. X.NXR "space command"
  944. X.NXR "file system" "disk usage per user"
  945. XThe
  946. X.PN space
  947. Xcommand maintains the disk usage for a file system on a user basis.
  948. X.SH Options
  949. X.TP
  950. X.B \-i filesystem
  951. XInitialize the data-base associated with the given file system. Only the super user can give this command.
  952. X.TP
  953. X.B \-u filesystem
  954. XUpdate the database for the given file system. Onlu the super user can give this command.
  955. X.TP
  956. X.B \-s filesystem user1 user2 ... usern
  957. XList the disk usage on the given filesystem for each users in arguments.
  958. X.TP
  959. X.B \-l filesystem
  960. XList the current disk usage for the given file system, sorted by most greedy users.
  961. X.TP
  962. X.B \-Ln filesystem
  963. XSame as option \-l but 
  964. X.I n
  965. Xdays in the past.
  966. X.TP
  967. X.B \-dn filesystem
  968. XList the difference in blocks between current usage and usage 
  969. X.I n
  970. Xdays in the past. 
  971. X.TP
  972. X.B \-Dn filesystem
  973. XList the difference in percentage between current usage and usage 
  974. X.I n
  975. Xdays in the past. 
  976. X.TP
  977. X.B \-tx
  978. XSummarize the disk usage on the whole system, depending on the 
  979. X.I x
  980. Xletter. 
  981. X.I c
  982. Xgives the current usage.
  983. X.I m
  984. Xgives the minimum usage.
  985. X.I M
  986. Xgives the maximum usage.
  987. X.SH Files
  988. XFile system names varies with system.
  989. X.br
  990. X/etc/passwd            to get user names
  991. X.br
  992. X/usr/src/space-xxx.data        for accumulated data for filesystem xxx
  993. X.SH See Also
  994. Xdu(1), ls(1), quot(8)
  995. X.SH Bugs
  996. XCertainly a lot. If you find one, send a mail to fmc@cnam.cnam.fr
  997. X
  998. SHAR_EOF
  999. $TOUCH -am 0213114791 space.8 &&
  1000. chmod 0444 space.8 ||
  1001. echo "restore of space.8 failed"
  1002. set `wc -c space.8`;Wc_c=$1
  1003. if test "$Wc_c" != "1534"; then
  1004.     echo original size 1534, current size $Wc_c
  1005. fi
  1006. fi
  1007. # ============= INSTALL ==============
  1008. if test X"$1" != X"-c" -a -f 'INSTALL'; then
  1009.     echo "File already exists: skipping 'INSTALL'"
  1010. else
  1011. echo "x - extracting INSTALL (Text)"
  1012. sed 's/^X//' << 'SHAR_EOF' > INSTALL &&
  1013. Xspace Version 1.9        Bugs, Gripes, etc... to fmc@cnam.cnam.fr
  1014. X                Last Modification:    12 Feb 91
  1015. X
  1016. Xspace is a maintenance tool used to watch disk-space usage on a per
  1017. Xuser per day basis. Be warned that you need :
  1018. X
  1019. X1/ root privilege to update the data-base (not to read it).
  1020. X
  1021. X2/ 1488 bytes per user per file-system, for each user UID possessing a
  1022. X   file on a file-system. Here we have around 300 users, 6
  1023. X   file-systems are checked, giving us 496 user/fs entries or
  1024. X   738048 bytes.
  1025. X
  1026. X3/ Right now, this usage is ... on a year by year basis. It means that
  1027. X     1/ Each year, you have to re-initialize the DB
  1028. X     2/ The starting point of the record keeping is hard-wired in the
  1029. X    code.
  1030. X    In fact, the rationale behind STARTDAY definition is not quite
  1031. X    clear. It will be used in the futur, but right now, it's only
  1032. X    use is to save some space (If you begin checking on the 1st Feb, 
  1033. X    #define STARTDAY 31 and #define TOKEEP 334).
  1034. X   In a (hopefully) near future, space will read a configuration file
  1035. X   to determine such parameters.
  1036. X
  1037. X4/ Finally, space haws only be tested on :
  1038. X
  1039. X    1/ A Vax running Ultrix (3.1 and now 4.0) using gcc
  1040. X    2/ A Sony MIPS running sony-os (3.3 and now 4.0) with mips-cc.
  1041. X
  1042. X   I think the code in sysdep.c is rather BSD-dependent, but I've no
  1043. X   SysV box to test it.
  1044. X
  1045. XHow to Compile.
  1046. X
  1047. XIn the best case do a make depend, followed by a make all and a make install.
  1048. X
  1049. XI think everything system dependent resides in sysdep.c and it's there
  1050. Xyou should check for trouble.
  1051. X
  1052. XCOMPILATION options.
  1053. X
  1054. XThe following #defines resides in defs.h change them if the default
  1055. Xvalue doesn't correspond to your needs/environment :
  1056. X
  1057. Xname        default value    meaning
  1058. XTOKEEP        365        How many days are stored.
  1059. XMAXUSERS    9999        Maximum number of users (should be enough:-)
  1060. XMAXFS        10        Maximum number of fs checked.
  1061. XDATADIR        "/usr/tmp"    Where to keep the DBs
  1062. XLOGFILE        "/usr/tmp/space.log"    The log file name.
  1063. XSTARTDAY    0        First Day in the record (from 1st Jan.)
  1064. XFSNAME        not defined    To check the fs type for local fs only.
  1065. XDESTDIR        /usr/local/bin    In the Makefile for make install.
  1066. X
  1067. XHow to Install.
  1068. X
  1069. Xmake install (hopefully). You then must :
  1070. X    1/ Initialize the DBs for each fs checked by :
  1071. X      for fs in fs1 fs2 ... fsn ; do space -i $fs ; done
  1072. X       space -i fs1 will look for the /dev/rfs1 file.
  1073. X
  1074. X    2/ Make sure the DBs are updated once a day (there's no check
  1075. X       to see if the DBs were already updated or not.) by doing
  1076. X      for fs in fs1 fs2 ... fsn ; do space -u $f ; done
  1077. X       The simplest way is to run it from cron, at night :-)
  1078. X
  1079. XHow to Use.
  1080. X
  1081. XThe most useful option are :
  1082. X
  1083. X -- space -l fs1
  1084. X    which will list, by decreasing order, all users with the disk space 
  1085. X    they are currently using on /dev/rfs1.
  1086. X
  1087. X -- space -dn fs1
  1088. X    which will list, by decreasing order, the variation of the disk space
  1089. X    used between 'n' days ago and today.
  1090. X
  1091. XOther options include :
  1092. X
  1093. X -- space -s fs1 user1 user2 ... userN
  1094. X    last 32 days space usage on /dev/rfs1 for each user name mentionned
  1095. X
  1096. X -- space -Ln fs1
  1097. X    last 'n' days space usage on dev/rfs1 for each users.
  1098. X
  1099. X -- space -Dn fs1
  1100. X    same as -dn but display percentage instead of difference.
  1101. X
  1102. X -- space -tx
  1103. X    display disk usage for everybody on every local fs in /etc/fstab.
  1104. X    the 'x' has the following meaning :
  1105. X    - space -tc or space -t        List Current Usage.
  1106. X    - space -tm or space -t-    List Minimum Usage.
  1107. X    - space -tM or space -t+    List Maximum Usage.
  1108. X    Really useful if all file-systems are checked.
  1109. X
  1110. X
  1111. XFutur modifications.
  1112. X
  1113. XThe main modification will be to introduce some sort of config. file 
  1114. Xcontaining all parameters wich are now #define'd.
  1115. X
  1116. XI also plane to introduce some sort of "time granularity" to enable
  1117. Xthe check to be done on a 1 hour basis or every 2 days, and so on.
  1118. X
  1119. XI also intend to add code to get ride of old users and extend the
  1120. Xlife time of the DBs for more than a year.
  1121. X
  1122. XAnd, of course, I'll try to fix bugs as they are reported. Space is 
  1123. Xrunning on our site for more than a 4 months now without much trouble,
  1124. Xbut it as only be tested on the configuration mentionned above.
  1125. X
  1126. SHAR_EOF
  1127. $TOUCH -am 0213114691 INSTALL &&
  1128. chmod 0644 INSTALL ||
  1129. echo "restore of INSTALL failed"
  1130. set `wc -c INSTALL`;Wc_c=$1
  1131. if test "$Wc_c" != "4037"; then
  1132.     echo original size 4037, current size $Wc_c
  1133. fi
  1134. fi
  1135. exit 0
  1136.  
  1137.                             [fmc]
  1138.  
  1139. -------------------------------------------------------------------------------
  1140. Frederic Chauveau             Conservatoire National des Arts et Metiers
  1141. fmc@cnam.cnam.fr
  1142. -------------------------------------------------------------------------------
  1143. Paradise is exactly like where you are right now, only much, much better.
  1144.                                William S. Burroughs
  1145. -------------------------------------------------------------------------------
  1146.  
  1147. exit 0 # Just in case...
  1148. -- 
  1149. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1150. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1151. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1152. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1153.