date and time created 83/02/11 15:44:33 by rrh
[unix-history] / usr / src / usr.bin / du / du.c
index df28a30..4089ba7 100644 (file)
-static char *sccsid = "@(#)du.c        4.2 (Berkeley) %G%";
+#ifndef lint
+static char *sccsid = "@(#)du.c        4.8 (Berkeley) %G%";
+#endif
+
 #include <stdio.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <sys/param.h>
 #include <sys/stat.h>
-#include <sys/dir.h>
-#define EQ(x,y)        (strcmp(x,y)==0)
-#define ML     1000
+#include <dir.h>
+
+char   path[BUFSIZ], name[BUFSIZ];
+int    aflg;
+int    sflg;
+char   *dot = ".";
 
 
-struct stat Statb;
-char   path[256], name[256];
-int    Aflag = 0,
-       Sflag = 0,
-       Noarg = 0;
+#define ML     1000
 struct {
 struct {
-       int     dev,
-               ino;
+       int     dev;
+       ino_t   ino;
 } ml[ML];
 } ml[ML];
+int    mlx;
+
 long   descend();
 long   descend();
-char   *rindex();
-char   *strcpy();
+char   *index(), *rindex(), *strcpy(), *sprintf();
 
 main(argc, argv)
 
 main(argc, argv)
-char **argv;
+       int argc;
+       char **argv;
 {
 {
-       register        i = 1;
-       long    blocks = 0;
-       register char   *np;
+       long kbytes = 0;
+       register char *np;
+       int pid;
 
 
-       if (argc>1) {
-               if(EQ(argv[i], "-s")) {
-                       ++i;
-                       ++Sflag;
-               } else if(EQ(argv[i], "-a")) {
-                       ++i;
-                       ++Aflag;
-               }
+       argc--, argv++;
+again:
+       if (argc && !strcmp(*argv, "-s")) {
+               sflg++;
+               argc--, argv++;
+               goto again;
+       }
+       if (argc && !strcmp(*argv, "-a")) {
+               aflg++;
+               argc--, argv++;
+               goto again;
+       }
+       if (argc == 0) {
+               argv = &dot;
+               argc = 1;
        }
        }
-       if(i == argc)
-               ++Noarg;
-
        do {
        do {
-               strcpy(path, Noarg? ".": argv[i]);
-               strcpy(name, path);
-               if(np = rindex(name, '/')) {
-                       *np++ = '\0';
-                       if(chdir(*name? name: "/") == -1) {
-                               fprintf(stderr, "cannot chdir()\n");
+               if (argc > 1) {
+                       pid = fork();
+                       if (pid == -1) {
+                               fprintf(stderr, "No more processes.\n");
                                exit(1);
                        }
                                exit(1);
                        }
-               } else
-                       np = path;
-               blocks = descend(path, *np? np: ".");
-               if(Sflag)
-                       printf("%ld     %s\n", blocks, path);
-       } while(++i < argc);
-
+                       if (pid != 0)
+                               wait((int *)0);
+               }
+               if (argc == 1 || pid == 0) {
+                       (void) strcpy(path, *argv);
+                       (void) strcpy(name, *argv);
+                       if (np = rindex(name, '/')) {
+                               *np++ = '\0';
+                               if (chdir(*name ? name : "/") < 0) {
+                                       perror(*name ? name : "/");
+                                       exit(1);
+                               }
+                       } else
+                               np = path;
+                       kbytes = descend(path, *np ? np : ".");
+                       if (sflg)
+                               printf("%ld\t%s\n", kbytes, path);
+                       if (argc > 1)
+                               exit(1);
+               }
+               argc--, argv++;
+       } while (argc > 0);
        exit(0);
 }
 
        exit(0);
 }
 
+DIR    *dirp = NULL;
+
 long
 long
-descend(np, fname)
-char *np, *fname;
+descend(base, name)
+       char *base, *name;
 {
 {
-       int dir = 0, /* open directory */
-               offset,
-               dsize,
-               entries,
-               dirsize;
-
-       struct direct dentry[BUFSIZ / sizeof (struct direct)];
-       register  struct direct *dp;
-       register char *c1, *c2;
+       char *ebase0, *ebase;
+       struct stat stb;
        int i;
        int i;
-       char *endofname;
-       long blocks = 0;
+       long kbytes = 0;
+       long curoff = NULL;
+       register struct direct *dp;
 
 
-       if(stat(fname,&Statb)<0) {
-               fprintf(stderr, "--bad status < %s >\n", name);
-               return 0L;
+       ebase0 = ebase = index(base, 0);
+       if (ebase > base && ebase[-1] == '/')
+               ebase--;
+       if (lstat(name, &stb) < 0) {
+               perror(base);
+               *ebase0 = 0;
+               return (0);
        }
        }
-       if(Statb.st_nlink > 1 && (Statb.st_mode&S_IFMT)!=S_IFDIR) {
-               static linked = 0;
-
-               for(i = 0; i <= linked; ++i) {
-                       if(ml[i].ino==Statb.st_ino && ml[i].dev==Statb.st_dev)
-                               return 0;
-               }
-               if (linked < ML) {
-                       ml[linked].dev = Statb.st_dev;
-                       ml[linked].ino = Statb.st_ino;
-                       ++linked;
+       if (stb.st_nlink > 1 && (stb.st_mode&S_IFMT) != S_IFDIR) {
+               for (i = 0; i <= mlx; i++)
+                       if (ml[i].ino == stb.st_ino && ml[i].dev == stb.st_dev)
+                               return (0);
+               if (mlx < ML) {
+                       ml[mlx].dev = stb.st_dev;
+                       ml[mlx].ino = stb.st_ino;
+                       mlx++;
                }
        }
                }
        }
-       blocks = (Statb.st_size + 1023-1) >> 10;
-       if((Statb.st_mode&S_IFMT)!=S_IFDIR) {
-               if(Aflag)
-                       printf("%ld     %s\n", blocks, np);
-               return(blocks);
+       kbytes = howmany(stb.st_size, 1024);
+       if ((stb.st_mode&S_IFMT) != S_IFDIR) {
+               if (aflg)
+                       printf("%ld\t%s\n", kbytes, base);
+               return (kbytes);
        }
        }
-
-       for(c1 = np; *c1; ++c1);
-       if(*(c1-1) == '/')
-               --c1;
-       endofname = c1;
-       dirsize = Statb.st_size;
-       if(chdir(fname) == -1)
-               return 0;
-       for(offset=0; offset < dirsize; offset += BUFSIZ) { /* each block */
-               dsize = BUFSIZ<(dirsize-offset)? BUFSIZ: (dirsize-offset);
-               if(!dir) {
-                       if((dir=open(".",0))<0) {
-                               fprintf(stderr, "--cannot open < %s >\n",
-                                       np);
-                               goto ret;
-                       }
-                       if(offset) lseek(dir, (long)offset, 0);
-                       if(read(dir, (char *)dentry, dsize)<0) {
-                               fprintf(stderr, "--cannot read < %s >\n",
-                                       np);
-                               goto ret;
-                       }
-                       if(dir > 10) {
-                               close(dir);
-                               dir = 0;
-                       }
-               } else 
-                       if(read(dir, (char *)dentry, dsize)<0) {
-                               fprintf(stderr, "--cannot read < %s >\n",
-                                       np);
-                               goto ret;
+       if (dirp != NULL)
+               closedir(dirp);
+       dirp = opendir(name);
+       if (dirp == NULL) {
+               perror(base);
+               *ebase0 = 0;
+               return (0);
+       }
+       if (chdir(name) < 0) {
+               perror(base);
+               *ebase0 = 0;
+               closedir(dirp);
+               dirp = NULL;
+               return (0);
+       }
+       while (dp = readdir(dirp)) {
+               if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+                       continue;
+               (void) sprintf(ebase, "/%s", dp->d_name);
+               curoff = telldir(dirp);
+               kbytes += descend(base, ebase+1);
+               *ebase = 0;
+               if (dirp == NULL) {
+                       dirp = opendir(".");
+                       if (dirp == NULL) {
+                               perror(".");
+                               return (0);
                        }
                        }
-               for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) {
-                       /* each directory entry */
-                       if(dp->d_ino==0
-                       || EQ(dp->d_name, ".")
-                       || EQ(dp->d_name, ".."))
-                               continue;
-                       c1 = endofname;
-                       *c1++ = '/';
-                       c2 = dp->d_name;
-                       for(i=0; i<DIRSIZ; ++i)
-                               if(*c2)
-                                       *c1++ = *c2++;
-                               else
-                                       break;
-                       *c1 = '\0';
-                       if(c1 == endofname) /* ?? */
-                               return 0L;
-                       blocks += descend(np, endofname+1);
+                       seekdir(dirp, curoff);
                }
        }
                }
        }
-       *endofname = '\0';
-       if(!Sflag)
-               printf("%ld     %s\n", blocks, np);
-ret:
-       if(dir)
-               close(dir);
-       if(chdir("..") == -1) {
-               *endofname = '\0';
-               fprintf(stderr, "Bad directory <%s>\n", np);
-               while(*--endofname != '/');
-               *endofname = '\0';
-               if(chdir(np) == -1)
-                       exit(1);
+       closedir(dirp);
+       dirp = NULL;
+       if (sflg == 0)
+               printf("%ld\t%s\n", kbytes, base);
+       if (chdir("..") < 0) {
+               (void) sprintf(index(base, 0), "/..");
+               perror(base);
+               exit(1);
        }
        }
-       return(blocks);
+       *ebase0 = 0;
+       return (kbytes);
 }
 }