home *** CD-ROM | disk | FTP | other *** search
- #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
-
- struct stat Statb;
- char path[256], name[256];
- int Aflag = 0,
- Sflag = 0,
- Noarg = 0;
- struct {
- int dev,
- ino;
- } ml[ML];
- long descend();
- char *rindex();
- char *strcpy();
-
- main(argc, argv)
- char **argv;
- {
- register i = 1;
- long blocks = 0;
- register char *np;
-
- if (argc>1) {
- if(EQ(argv[i], "-s")) {
- ++i;
- ++Sflag;
- } else if(EQ(argv[i], "-a")) {
- ++i;
- ++Aflag;
- }
- }
- if(i == argc)
- ++Noarg;
-
- 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");
- exit(1);
- }
- } else
- np = path;
- blocks = descend(path, *np? np: ".");
- if(Sflag)
- printf("%ld %s\n", blocks, path);
- } while(++i < argc);
-
- exit(0);
- }
-
- long
- descend(np, fname)
- char *np, *fname;
- {
- int dir = 0, /* open directory */
- offset,
- dsize,
- entries,
- dirsize;
-
- struct direct dentry[32];
- register struct direct *dp;
- register char *c1, *c2;
- int i;
- char *endofname;
- long blocks = 0;
-
- if(stat(fname,&Statb)<0) {
- fprintf(stderr, "--bad status < %s >\n", name);
- return 0L;
- }
- 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;
- }
- }
- blocks = (Statb.st_size + BSIZE-1) >> BSHIFT;
-
- if((Statb.st_mode&S_IFMT)!=S_IFDIR) {
- if(Aflag)
- printf("%ld %s\n", blocks, np);
- return(blocks);
- }
-
- 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 += 512) { /* each block */
- dsize = 512<(dirsize-offset)? 512: (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;
- }
- 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);
- }
- }
- *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);
- }
- return(blocks);
- }
-