1 static char *sccsid = "@(#)du.c 4.1 (Berkeley) 10/01/80"; 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 /* 95 blocks = (Statb.st_size + BSIZE-1) >> BSHIFT; 96 */ 97 blocks = (Statb.st_size + 511) >> 9; 98 99 if((Statb.st_mode&S_IFMT)!=S_IFDIR) { 100 if(Aflag) 101 printf("%ld %s\n", blocks, np); 102 return(blocks); 103 } 104 105 for(c1 = np; *c1; ++c1); 106 if(*(c1-1) == '/') 107 --c1; 108 endofname = c1; 109 dirsize = Statb.st_size; 110 if(chdir(fname) == -1) 111 return 0; 112 for(offset=0; offset < dirsize; offset += BUFSIZ) { /* each block */ 113 dsize = BUFSIZ<(dirsize-offset)? BUFSIZ: (dirsize-offset); 114 if(!dir) { 115 if((dir=open(".",0))<0) { 116 fprintf(stderr, "--cannot open < %s >\n", 117 np); 118 goto ret; 119 } 120 if(offset) lseek(dir, (long)offset, 0); 121 if(read(dir, (char *)dentry, dsize)<0) { 122 fprintf(stderr, "--cannot read < %s >\n", 123 np); 124 goto ret; 125 } 126 if(dir > 10) { 127 close(dir); 128 dir = 0; 129 } 130 } else 131 if(read(dir, (char *)dentry, dsize)<0) { 132 fprintf(stderr, "--cannot read < %s >\n", 133 np); 134 goto ret; 135 } 136 for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) { 137 /* each directory entry */ 138 if(dp->d_ino==0 139 || EQ(dp->d_name, ".") 140 || EQ(dp->d_name, "..")) 141 continue; 142 c1 = endofname; 143 *c1++ = '/'; 144 c2 = dp->d_name; 145 for(i=0; i<DIRSIZ; ++i) 146 if(*c2) 147 *c1++ = *c2++; 148 else 149 break; 150 *c1 = '\0'; 151 if(c1 == endofname) /* ?? */ 152 return 0L; 153 blocks += descend(np, endofname+1); 154 } 155 } 156 *endofname = '\0'; 157 if(!Sflag) 158 printf("%ld %s\n", blocks, np); 159 ret: 160 if(dir) 161 close(dir); 162 if(chdir("..") == -1) { 163 *endofname = '\0'; 164 fprintf(stderr, "Bad directory <%s>\n", np); 165 while(*--endofname != '/'); 166 *endofname = '\0'; 167 if(chdir(np) == -1) 168 exit(1); 169 } 170 return(blocks); 171 } 172