ast@cs.vu.nl (Andy Tanenbaum) (06/07/87)
Here is a version of du - the disk usage program. It was written by Alistair G. Crooks and given to me for posting. I have modified it slightly in the process. Andy Tanenbaum (ast@cs.vu.nl) -----------------------------cut here ------------------- /* du - report on disk usage Author: Alistair G. Crooks */ /* * du.c 1.1 27/5/87 agc Joypace Ltd. * * Copyright 1987, Joypace Ltd., London UK. All rights reserved. * This code may be freely distributed, provided that this notice * remains attached. * * du - a public domain interpretation of du(1). * * Note that du does not report on inode blocks and other overhead, * so the sizes it reports do not agree with those of df. */ #include "stdio.h" #include "stat.h" #include "blocksize.h" char *prog; /* program name */ char *optstr = "as"; /* -a and -s arguments */ int silent = 0; /* silent mode */ int all = 0; /* all directory entries mode */ char *startdir = "."; /* starting from here */ #define LINELEN 256 #define DIRNAMELEN 14 #define LSTAT stat typedef struct _dirstr { int inum; char d_name[DIRNAMELEN]; } DIR; DIR dir; #define ino_t unsigned short typedef struct _alstr { int al_dev; ino_t al_inum; } ALREADY; #define MAXALREADY 50 ALREADY already[MAXALREADY]; int alc = 0; /* * myindex - stop the scanf bug */ char *myindex(s, c) register char *s; register char c; { for (; *s; s++) if (*s == c) return(s); return(NULL); } /* * getopt - parse the arguments given. * retrieved from net.sources */ int opterr = 1; int optind = 1; int optopt; char *optarg; #define BADCH (int)'?' #define EMSG "" #define TELL(s) fputs(*nargv, stderr); fputs(s, stderr);\ fputc(optopt, stderr); fputc('\n', stderr);\ return(BADCH); int getopt(nargc, nargv, ostr) int nargc; char **nargv; char *ostr; { register char *oli; static char *place = EMSG; if (!*place) { if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF); if (*place == '-') { ++optind; return(EOF); } } if ((optopt = (int)*place++) == (int)':' || !(oli = myindex(ostr, optopt))) { if (!*place) ++optind; TELL(": illegal option -- "); } if (*++oli != ':') { optarg = NULL; if (!*place) ++optind; } else { if (*place) optarg = place; else if (nargc <= ++optind) { place = EMSG; TELL(": option requires an argument -- "); } else optarg = nargv[optind]; place = EMSG; ++optind; } return(optopt); } /* * makedname - make the direcory entry from the directory name, * and the file name, placing it in out. If this would overflow, * return 0, otherwise 1. */ int makedname(d, f, out, outlen) char *d; char *f; char *out; int outlen; { char *cp; if (strlen(d) + strlen(f) + 2 > outlen) return(0); for (cp = out ; *d ; *cp++ = *d++) ; if (*(cp-1) != '/') *cp++ = '/'; while (*f) *cp++ = *f++; *cp = '\0'; return(1); } /* * done - have we encountered (dev, inum) before? Returns 1 for yes, * 0 for no, and remembers (dev, inum). */ int done(dev, inum) int dev; ino_t inum; { register ALREADY *ap; register int i; int ret = 0; for (i = 0, ap = already ; i < alc ; ap++, i++) if (ap->al_dev == dev && ap->al_inum == inum) { ret = 1; break; } if (alc < MAXALREADY) { already[alc].al_dev = dev; already[alc++].al_inum = inum; } return(ret); } /* * dodir - process the directory d. Return the long size (in blocks) * of d and its descendants. */ long dodir(d) char *d; { struct stat s; long total = 0L; char dent[LINELEN]; int fd; if ((fd = open(d, 0)) < 0) return(0L); while (read(fd, &dir, sizeof(dir)) > 0) { if (strcmp(dir.d_name, ".") == 0 || strcmp(dir.d_name, "..") == 0) continue; if (dir.inum == 0) continue; if (!makedname(d, dir.d_name, dent, sizeof(dent))) continue; if (LSTAT(dent, &s) < 0) continue; if (s.st_nlink > 1 && done(s.st_dev, s.st_ino)) continue; if ((s.st_mode & S_IFMT) == S_IFDIR) total += dodir(dent); switch(s.st_mode & S_IFMT) { case S_IFREG: case S_IFDIR: total += (s.st_size + BLOCK_SIZE) / BLOCK_SIZE; break; } if (all && (s.st_mode & S_IFMT) != S_IFDIR) printf("%D\t%s\n", (s.st_size + BLOCK_SIZE) / BLOCK_SIZE, dent); } close(fd); if (!silent) printf("%D\t%s\n", total, d); return(total); } /* * OK, here goes... */ main(argc, argv) int argc; char **argv; { long tot; int c; prog = argv[0]; while ((c = getopt(argc, argv, optstr)) != EOF) switch(c) { case 'a' : all = 1; break; case 's' : silent = 1; break; default : fprintf(stderr, "Usage: %s [-a] [-s] [startdir]\n", prog); exit(1); } if (optind < argc) startdir = argv[optind]; tot = dodir(startdir); if (silent) printf("%D\t%s\n", tot, startdir); exit(0); }
go@orstcs.UUCP (06/13/87)
Not to start a war (this belongs in *.legal anyway...) Regarding the recent "du" posting: "... All rights reserved ..." "... public domain ..." "Public domain" means "no rights reserved." I do wish folks wouldn't try to confuse me. This is just a comment -- no ill will intended, really. Thanks for the program -- I was hoping one of these would come along. Gary Oliver ...!hplabs!hp-pcd!orstcs!squint!go