1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif /* not lint */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)df.c 5.3 (Berkeley) 01/10/88"; 15 #endif /* not lint */ 16 17 #include <sys/param.h> 18 #include <sys/fs.h> 19 #include <sys/stat.h> 20 #include <errno.h> 21 22 #include <stdio.h> 23 #include <fstab.h> 24 #include <mtab.h> 25 26 /* 27 * df 28 */ 29 struct mtab mtab[NMOUNT]; 30 char root[32]; 31 char *mpath(); 32 33 int iflag; 34 35 union { 36 struct fs iu_fs; 37 char dummy[SBSIZE]; 38 } sb; 39 #define sblock sb.iu_fs 40 41 int fi; 42 daddr_t alloc(); 43 char *strcpy(); 44 45 main(argc, argv) 46 int argc; 47 char **argv; 48 { 49 int i; 50 51 while (argc > 1 && argv[1][0]=='-') { 52 switch (argv[1][1]) { 53 54 case 'i': 55 iflag++; 56 break; 57 58 default: 59 fprintf(stderr, "usage: df [ -i ] [ filsys... ]\n"); 60 exit(0); 61 } 62 argc--, argv++; 63 } 64 i = open("/etc/mtab", 0); 65 if (i >= 0) { 66 (void) read(i, (char *)mtab, sizeof (mtab)); 67 (void) close(i); 68 } 69 sync(); 70 printf("Filesystem kbytes used avail capacity"); 71 if (iflag) 72 printf(" iused ifree %%iused"); 73 printf(" Mounted on\n"); 74 if (argc <= 1) { 75 struct fstab *fsp; 76 77 if (setfsent() == 0) 78 perror(FSTAB), exit(1); 79 while (fsp = getfsent()) { 80 if (strcmp(fsp->fs_type, FSTAB_RW) && 81 strcmp(fsp->fs_type, FSTAB_RO) && 82 strcmp(fsp->fs_type, FSTAB_RQ)) 83 continue; 84 if (root[0] == 0) 85 (void) strcpy(root, fsp->fs_spec); 86 dfree(fsp->fs_spec, 1); 87 } 88 (void)endfsent(); 89 exit(0); 90 } 91 for (i=1; i<argc; i++) 92 dfree(argv[i], 0); 93 } 94 95 dfree(file, infsent) 96 char *file; 97 int infsent; 98 { 99 long totalblks, availblks, avail, free, used; 100 struct stat stbuf; 101 struct fstab *fsp; 102 103 if (stat(file, &stbuf) == 0 && 104 (stbuf.st_mode&S_IFMT) != S_IFCHR && 105 (stbuf.st_mode&S_IFMT) != S_IFBLK) { 106 if (infsent) { 107 fprintf(stderr, "%s: screwy /etc/fstab entry\n", file); 108 return; 109 } 110 (void)setfsent(); 111 while (fsp = getfsent()) { 112 struct stat stb; 113 114 if (stat(fsp->fs_spec, &stb) == 0 && 115 stb.st_rdev == stbuf.st_dev) { 116 file = fsp->fs_spec; 117 (void)endfsent(); 118 goto found; 119 } 120 } 121 (void)endfsent(); 122 fprintf(stderr, "%s: mounted on unknown device\n", file); 123 return; 124 } 125 found: 126 fi = open(file, 0); 127 if (fi < 0) { 128 perror(file); 129 return; 130 } 131 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) { 132 (void) close(fi); 133 return; 134 } 135 printf("%-12.12s", file); 136 totalblks = sblock.fs_dsize; 137 free = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + 138 sblock.fs_cstotal.cs_nffree; 139 used = totalblks - free; 140 availblks = totalblks * (100 - sblock.fs_minfree) / 100; 141 avail = availblks > used ? availblks - used : 0; 142 printf("%8d%8d%8d", totalblks * sblock.fs_fsize / 1024, 143 used * sblock.fs_fsize / 1024, avail * sblock.fs_fsize / 1024); 144 printf("%6.0f%%", 145 availblks == 0 ? 0.0 : (double) used / (double) availblks * 100.0); 146 if (iflag) { 147 int inodes = sblock.fs_ncg * sblock.fs_ipg; 148 used = inodes - sblock.fs_cstotal.cs_nifree; 149 printf("%8ld%8ld%6.0f%% ", used, sblock.fs_cstotal.cs_nifree, 150 inodes == 0 ? 0.0 : (double)used / (double)inodes * 100.0); 151 } else 152 printf(" "); 153 printf(" %s\n", mpath(file)); 154 (void) close(fi); 155 } 156 157 long lseek(); 158 159 bread(off, buf, cnt) 160 long off; 161 char *buf; 162 { 163 int n; 164 extern errno; 165 166 (void) lseek(fi, off, 0); 167 if ((n=read(fi, buf, cnt)) != cnt) { 168 /* probably a dismounted disk if errno == EIO */ 169 if (errno != EIO) { 170 printf("\nread error off = %ld\n", off); 171 printf("count = %d; errno = %d\n", n, errno); 172 } 173 return (0); 174 } 175 return (1); 176 } 177 178 /* 179 * Given a name like /dev/rrp0h, returns the mounted path, like /usr. 180 */ 181 char * 182 mpath(file) 183 char *file; 184 { 185 register struct mtab *mp; 186 187 if (eq(file, root)) 188 return ("/"); 189 for (mp = mtab; mp < mtab + NMOUNT; mp++) 190 if (eq(file, mp->m_dname)) 191 return (mp->m_path); 192 return ""; 193 } 194 195 eq(f1, f2) 196 char *f1, *f2; 197 { 198 199 if (strncmp(f1, "/dev/", 5) == 0) 200 f1 += 5; 201 if (strncmp(f2, "/dev/", 5) == 0) 202 f2 += 5; 203 if (!strcmp(f1, f2)) 204 return (1); 205 if (*f1 == 'r' && !strcmp(f1+1, f2)) 206 return (1); 207 if (*f2 == 'r' && !strcmp(f1, f2+1)) 208 return (1); 209 if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0) 210 return (1); 211 return (0); 212 } 213