1 static char *sccsid = "@(#)df.c 4.4 (Berkeley) 03/10/81"; 2 #include <stdio.h> 3 #include <fstab.h> 4 #include <sys/param.h> 5 #include <sys/filsys.h> 6 #include <sys/fblk.h> 7 #include <sys/stat.h> 8 /* 9 * df 10 */ 11 12 #define NFS 20 /* Max number of filesystems */ 13 14 struct { 15 char path[32]; 16 char spec[32]; 17 } mtab[NFS]; 18 char root[32]; 19 20 char *mpath(); 21 22 daddr_t blkno = 1; 23 24 int lflag; 25 int iflag; 26 27 struct filsys sblock; 28 29 int fi; 30 daddr_t alloc(); 31 32 main(argc, argv) 33 char **argv; 34 { 35 int i; 36 char buf[128]; 37 38 while (argc >= 1 && argv[1][0]=='-') { 39 switch(argv[1][1]) { 40 41 case 'l': 42 lflag++; 43 break; 44 45 case 'i': 46 iflag++; 47 break; 48 49 default: 50 fprintf(stderr, "usage: df [ -il ] [ filsys... ]\n"); 51 exit(0); 52 } 53 argc--, argv++; 54 } 55 56 if ((i=open("/etc/mtab", 0)) >= 0) { 57 read(i, mtab, sizeof mtab); /* Probably returns short */ 58 close(i); 59 } 60 printf("Filesystem Mounted on blocks\t used\t free"); 61 if (lflag) 62 printf("\thardway"); 63 printf("\t%% used"); 64 if (iflag) 65 printf("\tiused\tifree\t%%iused"); 66 putchar('\n'); 67 if(argc <= 1) { 68 struct fstab *fsp; 69 if (setfsent() == 0) 70 perror(FSTAB), exit(1); 71 while( (fsp = getfsent()) != 0){ 72 if ( (strcmp(fsp->fs_type, FSTAB_RW) != 0) 73 &&(strcmp(fsp->fs_type, FSTAB_RO) != 0) ) 74 continue; 75 if (root[0] == 0) 76 strcpy(root, fsp->fs_spec); 77 dfree(fsp->fs_spec); 78 } 79 endfsent(); 80 exit(0); 81 } 82 83 for(i=1; i<argc; i++) { 84 dfree(argv[i]); 85 } 86 } 87 88 dfree(file) 89 char *file; 90 { 91 daddr_t i; 92 long blocks; 93 long free; 94 long used; 95 long hardway; 96 char *mp; 97 struct stat stbuf; 98 99 if(stat(file, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) != S_IFCHR 100 && (stbuf.st_mode&S_IFMT) != S_IFBLK) { 101 int mt = open("/etc/mtab", 0), len; 102 char *str = "/dev/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 103 char mtab[32]; 104 struct stat mstbuf; 105 while((len = read(mt, mtab, 32)) == 32) { 106 read(mt, &str[5], 32); 107 if(stat(str, &mstbuf) == 0 && mstbuf.st_rdev == stbuf.st_dev) { 108 file = str; 109 break; 110 } 111 } 112 close(mt); 113 if(len == 0) { 114 fprintf(stderr, "%s: mounted on unknown device\n", file); 115 return; 116 } 117 } 118 fi = open(file, 0); 119 if(fi < 0) { 120 fprintf(stderr,"cannot open %s\n", file); 121 return; 122 } 123 sync(); 124 bread(1L, (char *)&sblock, sizeof(sblock)); 125 printf("%-12.12s%s", file, mp = mpath(file)); 126 if (strlen(mp) < 4) 127 putchar('\t'); 128 129 blocks = (long) sblock.s_fsize - (long)sblock.s_isize; 130 free = sblock.s_tfree; 131 used = blocks - free; 132 133 printf("\t%6ld", blocks); 134 printf("\t%6ld", used); 135 printf("\t%6ld", free); 136 if (lflag) { 137 hardway = 0; 138 while(alloc()) 139 hardway++; 140 printf("\t%6ld", free=hardway); 141 } 142 printf("\t%5.0f%%", 143 blocks == 0 ? 0.0 : (double) used / (double)blocks * 100.0); 144 if (iflag) { 145 int inodes = (sblock.s_isize - 2) * INOPB; 146 used = inodes - sblock.s_tinode; 147 printf("\t%5ld\t%5ld\t%5.0f%%", used, sblock.s_tinode, 148 inodes == 0 ? 0.0 : (double)used/(double)inodes*100.0); 149 } 150 printf("\n"); 151 close(fi); 152 } 153 154 daddr_t 155 alloc() 156 { 157 int i; 158 daddr_t b; 159 struct fblk buf; 160 161 i = --sblock.s_nfree; 162 if(i<0 || i>=NICFREE) { 163 printf("bad free count, b=%D\n", blkno); 164 return(0); 165 } 166 b = sblock.s_free[i]; 167 if(b == 0) 168 return(0); 169 if(b<sblock.s_isize || b>=sblock.s_fsize) { 170 printf("bad free block (%D)\n", b); 171 return(0); 172 } 173 if(sblock.s_nfree <= 0) { 174 bread(b, (char *)&buf, sizeof(buf)); 175 blkno = b; 176 sblock.s_nfree = buf.df_nfree; 177 for(i=0; i<NICFREE; i++) 178 sblock.s_free[i] = buf.df_free[i]; 179 } 180 return(b); 181 } 182 183 bread(bno, buf, cnt) 184 daddr_t bno; 185 char *buf; 186 { 187 int n; 188 extern errno; 189 190 lseek(fi, bno<<BSHIFT, 0); 191 if((n=read(fi, buf, cnt)) != cnt) { 192 printf("\nread error bno = %ld\n", bno); 193 printf("count = %d; errno = %d\n", n, errno); 194 exit(0); 195 } 196 } 197 198 /* 199 * Given a name like /dev/rrp0h, returns the mounted path, like /usr. 200 */ 201 char *mpath(file) 202 char *file; 203 { 204 register int i; 205 206 if (eq(file, root)) 207 return "/"; 208 for (i=0; i<NFS; i++) 209 if (eq(file, mtab[i].spec)) 210 return mtab[i].path; 211 return ""; 212 } 213 214 eq(f1, f2) 215 char *f1, *f2; 216 { 217 if (strncmp(f1, "/dev/", 5) == 0) 218 f1 += 5; 219 if (strncmp(f2, "/dev/", 5) == 0) 220 f2 += 5; 221 if (strcmp(f1, f2) == 0) 222 return 1; 223 if (*f1 == 'r' && strcmp(f1+1, f2) == 0) 224 return 1; 225 if (*f2 == 'r' && strcmp(f1, f2+1) == 0) 226 return 1; 227 if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0) 228 return 1; 229 return 0; 230 } 231