1 static char *sccsid = "@(#)du.c 4.2 (Berkeley) 03/10/82"; 2 #include <stdio.h> 3 #include <sys/param.h> 4 #include <sys/stat.h> 5 #include <sys/dir.h> 6 #define EQ(x,y) (strcmp(x,y)==0) 7 #define ML 1000 8 9 struct stat Statb; 10 char path[256], name[256]; 11 int Aflag = 0, 12 Sflag = 0, 13 Noarg = 0; 14 struct { 15 int dev, 16 ino; 17 } ml[ML]; 18 long descend(); 19 char *rindex(); 20 char *strcpy(); 21 22 main(argc, argv) 23 char **argv; 24 { 25 register i = 1; 26 long blocks = 0; 27 register char *np; 28 29 if (argc>1) { 30 if(EQ(argv[i], "-s")) { 31 ++i; 32 ++Sflag; 33 } else if(EQ(argv[i], "-a")) { 34 ++i; 35 ++Aflag; 36 } 37 } 38 if(i == argc) 39 ++Noarg; 40 41 do { 42 strcpy(path, Noarg? ".": argv[i]); 43 strcpy(name, path); 44 if(np = rindex(name, '/')) { 45 *np++ = '\0'; 46 if(chdir(*name? name: "/") == -1) { 47 fprintf(stderr, "cannot chdir()\n"); 48 exit(1); 49 } 50 } else 51 np = path; 52 blocks = descend(path, *np? np: "."); 53 if(Sflag) 54 printf("%ld %s\n", blocks, path); 55 } while(++i < argc); 56 57 exit(0); 58 } 59 60 long 61 descend(np, fname) 62 char *np, *fname; 63 { 64 int dir = 0, /* open directory */ 65 offset, 66 dsize, 67 entries, 68 dirsize; 69 70 struct direct dentry[BUFSIZ / sizeof (struct direct)]; 71 register struct direct *dp; 72 register char *c1, *c2; 73 int i; 74 char *endofname; 75 long blocks = 0; 76 77 if(stat(fname,&Statb)<0) { 78 fprintf(stderr, "--bad status < %s >\n", name); 79 return 0L; 80 } 81 if(Statb.st_nlink > 1 && (Statb.st_mode&S_IFMT)!=S_IFDIR) { 82 static linked = 0; 83 84 for(i = 0; i <= linked; ++i) { 85 if(ml[i].ino==Statb.st_ino && ml[i].dev==Statb.st_dev) 86 return 0; 87 } 88 if (linked < ML) { 89 ml[linked].dev = Statb.st_dev; 90 ml[linked].ino = Statb.st_ino; 91 ++linked; 92 } 93 } 94 blocks = (Statb.st_size + 1023-1) >> 10; 95 if((Statb.st_mode&S_IFMT)!=S_IFDIR) { 96 if(Aflag) 97 printf("%ld %s\n", blocks, np); 98 return(blocks); 99 } 100 101 for(c1 = np; *c1; ++c1); 102 if(*(c1-1) == '/') 103 --c1; 104 endofname = c1; 105 dirsize = Statb.st_size; 106 if(chdir(fname) == -1) 107 return 0; 108 for(offset=0; offset < dirsize; offset += BUFSIZ) { /* each block */ 109 dsize = BUFSIZ<(dirsize-offset)? BUFSIZ: (dirsize-offset); 110 if(!dir) { 111 if((dir=open(".",0))<0) { 112 fprintf(stderr, "--cannot open < %s >\n", 113 np); 114 goto ret; 115 } 116 if(offset) lseek(dir, (long)offset, 0); 117 if(read(dir, (char *)dentry, dsize)<0) { 118 fprintf(stderr, "--cannot read < %s >\n", 119 np); 120 goto ret; 121 } 122 if(dir > 10) { 123 close(dir); 124 dir = 0; 125 } 126 } else 127 if(read(dir, (char *)dentry, dsize)<0) { 128 fprintf(stderr, "--cannot read < %s >\n", 129 np); 130 goto ret; 131 } 132 for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) { 133 /* each directory entry */ 134 if(dp->d_ino==0 135 || EQ(dp->d_name, ".") 136 || EQ(dp->d_name, "..")) 137 continue; 138 c1 = endofname; 139 *c1++ = '/'; 140 c2 = dp->d_name; 141 for(i=0; i<DIRSIZ; ++i) 142 if(*c2) 143 *c1++ = *c2++; 144 else 145 break; 146 *c1 = '\0'; 147 if(c1 == endofname) /* ?? */ 148 return 0L; 149 blocks += descend(np, endofname+1); 150 } 151 } 152 *endofname = '\0'; 153 if(!Sflag) 154 printf("%ld %s\n", blocks, np); 155 ret: 156 if(dir) 157 close(dir); 158 if(chdir("..") == -1) { 159 *endofname = '\0'; 160 fprintf(stderr, "Bad directory <%s>\n", np); 161 while(*--endofname != '/'); 162 *endofname = '\0'; 163 if(chdir(np) == -1) 164 exit(1); 165 } 166 return(blocks); 167 } 168