/* * df [-i] [specials] * * prints out number of free inodes (-i option) and number of free * blocks on the file systems listed (current file system by default). * Certain local abreviations for the file system names are accepted. * It is assumed that if a cooked device name is prefixed by * the letter `r', the corresponding raw device name results. */ #include <local-system> #include <filsys.h> #include <ino.h> /* * `prefix' is added to the given arguments - if this cannot be opened, * the argument itself is tried. * `rawp' is the corresponding raw device name. * OFFSET is the char offset to the X's (cooked dev). */ #ifdef EECF char prefix[] "/dev/msXX"; char rawp[] "/dev/rmsXX"; #define OFFSET 7 #endif #ifdef AGSM char prefix[] "/dev/hpXX"; char rawp[] "/dev/rhpXX"; #define OFFSET 7 #endif #ifdef EECF1140 char prefix[] "/dev/rkX"; char rawp[] "/dev/rrkX"; #define OFFSET 7 #endif #define IBLK 16 /* blocks of inodes per read */ struct { int ino; char name[14]; /* ino and name MUST be in this order */ int stbuf[18]; }; struct filsys sblock; int fi; /* file descriptor */ int cookedfd; /* file desc. of cooked dev */ int rawfd; /* file desc. of raw dev */ struct inode *inode; struct { unsigned unsd; }; main(argc, argv) char **argv; { register i, j; register char *fp; fp = argv[1]; if(argc >= 2 && *fp++ == '-' && *fp++ == 'i' && *fp == 0) { if((inode.unsd = sbrk(IBLK*16*sizeof *inode)) == -1) { inode = 0; printf("Not enough memory to count inodes\n"); } argc--; argv++; } if(argc <= 1) /* use current file system */ { stat("", sblock.stbuf); i = sblock.stbuf[0]; chdir("/dev"); j = open("", 0); fp = 0; while(read(j, &sblock, 16) > 0) { if(sblock.ino == 0) continue; stat(sblock.name, sblock.stbuf); if(((sblock.stbuf[2]&IFMT) == IFBLK) && (sblock.stbuf[6] == i)) { fp++; break; } } if(fp == 0) { printf("Can't find file system\n"); exit(1); } close(j); if((cookedfd = open(sblock.name, 0)) < 0) { printf("Cannot open /dev/%s\n", sblock.name); exit(1); } printf("/dev/%s ", sblock.name); if(inode) { sblock.name[-1] = 'r'; if((rawfd = open(&sblock.name[-1], 0)) < 0) rawfd = cookedfd; } dfree(); exit(0); } for(i = 1; i < argc; i++) { fp = argv[i]; j = OFFSET; while((prefix[j++] = *fp++) && j < sizeof prefix); prefix[j-1] = 0; if((cookedfd = open(prefix, 0)) < 0) { if((cookedfd = rawfd = open(argv[i], 0)) < 0) { printf("Cannot open %s\n", argv[i]); continue; } fp = argv[i]; } else { if(inode) { fp = argv[i]; j = OFFSET+1; while((rawp[j++] = *fp++) && j < sizeof rawp); rawp[j-1] = 0; if((rawfd = open(rawp, 0)) < 0) rawfd = cookedfd; } fp = prefix; } printf("%s ", fp); dfree(); } } dfree() { register i, j, ino; int cnt, ninodes; sync(); fi = cookedfd; bread(1, &sblock, 512); cnt = 0; ninodes = sblock.s_isize*16; if(inode) { fi = rawfd; for(i = 0, ino = 0; ino < ninodes; i =+ IBLK) { bread(i+2, inode, IBLK*16*sizeof *inode); for(j = 0; j < IBLK*16 && ino < ninodes; j++) { ino++; if((inode[j].i_mode&IALLOC) == 0) cnt++; } } printf("%d ", cnt); fi = cookedfd; } i = 0; while(alloc()) i++; printf("%d\n", i); close(fi); } alloc() { int b, i, buf[256]; i = --sblock.s_nfree; if(i < 0 || i >= 100) { printf("bad free count "); return(0); } b = sblock.s_free[i]; if(b == 0) return(0); if(b < sblock.s_isize+2 || b >= sblock.s_fsize) { printf("bad free block (%d)\n", b); return(0); } if(sblock.s_nfree <= 0) { bread(b, buf, 512); sblock.s_nfree = buf[0]; for(i = 0; i < 100; i++) sblock.s_free[i] = buf[i+1]; } return(b); } bread(bno, buf, cnt) { int n; extern errno; seek(fi, bno, 3); if((n = read(fi, buf, cnt)) != cnt) { printf("read error %d\n", bno); printf("count = %d; errno = %d\n", n, errno); exit(1); } } #ifdef SPRINTF #define NUMBERS #include <sprintf.h> #endif