dt@yenta.alb.nm.us (David B. Thomas) (11/15/90)
I just wrote a handy disk usage analyzer for news that I call "ndu", "news disk usage". Like everything in unix, there is probably some wonderful command I've never noticed that does exactly the same thing this program does, only much better. Then again, like everything in unix, this was fun to write! It tells you, for each newsgroup, how much space it uses (excluding subdirectories, unlike du(1)), how many articles are online, and the age of the oldest article. The output is in a format suitable for crunching by sort, awk, and them cats. ----- begin readme ----- ndu -- "news disk usage" ndu is a useful tool for analyzing the /usr/spool/news directory tree. While ndu can be used to gather information about any directory tree, it was designed to analyze /usr/spool/news, and will do so by default. Usage is: ndu [ directory ] The output shows, for each subdirectory (newsgroup) encountered, space used (in kb), number of files (articles), and the age of oldest file in days. The format of the output is suitable for feeding to sort, awk, and many other nifty tools to help you analyze what's there. Some sample output: 23 40 3 ./misc/test 71 46 1 ./misc/consumers/house 58 37 1 ./misc/consumers 144 52 1 ./misc/legal 71 67 3 ./misc/wanted 96 50 3 ./misc/invest 136 57 1 ./misc/kids 193 146 3 ./misc/forsale/computers 222 169 3 ./misc/forsale ^^^-------------------------------------------space used in kb ^^^-------------------------------------number of articles ^-------------------------------age in days of oldest article Space and number of articles do not include subdirectories or their contents. Note that misc/consumers/house exceeds misc/consumers in both space used and number of articles. Age is rounded down to the nearest day, so a 0 simply means that all files in that directory are less than 24 hours old. BUGS - All file names are listed beginning with "./". - It does not convert the paths to newsgroup names with periods. - It reads directories primitive-unix-style, so it probably won't work on a non-unix system without some minor hacking. Oh well, life is long and the program is short :-) ----- end readme ----- ----- begin ndu.c ----- /* * ndu.c -- news disk usage * * usage: ndu [ directory ] * * generates a disk usage report for all directories subordinate to and * including the path specified (default /usr/spool/news). * * Each line in the report shows space used in kb, number of files, and the * age of the oldest file in days. Space and number of files exclude * subdirectories and their contents, unlike du(1). * * Crufted up by: David B. Thomas <dt@yenta.alb.nm.us> * * This program is free and you can do anything you want with it, including * saving me some embarrassment by claiming you wrote it! * -dt */ #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/dir.h> #include <malloc.h> #define SECINDAY (24 * 3600) int dirfunc(); char *progname, *topdir = "/usr/spool/news"; time_t now; main(argc,argv) int argc; char *argv[]; { progname = argv[0]; switch (argc) { case 2: topdir = argv[1]; /* fallthru */ case 1: break; default: fprintf (stderr, "usage: %s [ directory ]\n", progname); exit (-1); } time(&now); chdir (topdir); dodir ("."); exit (0); } /* main() */ /* * dodir(path) * recursively explores directory specified by path, tallying and * reporting info as it goes. */ dodir(path) char *path; { /* these must be stacked */ int fd, nfiles = 0; size_t size = 0; time_t oldest = now; char *fullpath; /* these can be overwritten -- one static copy ok */ static char fname[DIRSIZ+1]; static struct direct dir; static struct stat stt; if ( (fd = open (path, O_RDONLY)) == -1) { fprintf (stderr, "%s: can't read %s\n", progname, path); return; } while (read(fd, &dir, sizeof(struct direct)) == sizeof(struct direct)) { /* make a null-terminated string with the filename */ strncpy (fname, dir.d_name, DIRSIZ); fname[DIRSIZ] = '\0'; /* skip . and .. and empty dir slots */ if (!dir.d_ino || !strcmp(fname,".") || !strcmp(fname,"..") ) continue; /* build the full path of this file */ fullpath = malloc (strlen(path)+strlen(fname)+2); sprintf (fullpath, "%s/%s", path, fname); if (stat(fullpath, &stt) == -1) { fprintf (stderr, "%s: cannot stat %s\n", progname, fullpath); free (fullpath); continue; } if (stt.st_mode & S_IFDIR) { dodir (fullpath); free (fullpath); continue; } free (fullpath); if (stt.st_mtime < oldest) oldest = stt.st_mtime; size += stt.st_size; ++nfiles; } close (fd); /* report size in kb, number of articles, age of oldest in days */ if (nfiles) printf ("%5d %5d %5d %s\n", size/1000, nfiles, (now-oldest) / SECINDAY, path); } /* dodir() */ ----- end ndu.c ----- Please send me any comments, mods, etc. --little david -- You mean you WUZ a Romanian....MUTHA!