1 /* 2 * Copyright (c) 1980 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)df.c 5.20 (Berkeley) 05/31/90"; 16 #endif /* not lint */ 17 18 /* 19 * df 20 */ 21 #include <sys/param.h> 22 #include <sys/stat.h> 23 #include <sys/mount.h> 24 #include <sys/file.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 char *getmntpt(); 30 int iflag, kflag, nflag; 31 #ifdef COMPAT_43 32 int oflag; 33 #endif /* COMPAT_43 */ 34 35 main(argc, argv) 36 int argc; 37 char **argv; 38 { 39 extern int errno, optind; 40 int err, ch, i; 41 long width, maxwidth, mntsize, getmntinfo(); 42 char *mntpt, *mktemp(); 43 struct stat stbuf; 44 struct statfs statfsbuf, *mntbuf; 45 struct ufs_args mdev; 46 47 while ((ch = getopt(argc, argv, "ikon")) != EOF) 48 switch(ch) { 49 case 'i': 50 iflag = 1; 51 break; 52 case 'k': 53 kflag = 1; 54 break; 55 case 'n': 56 nflag = 1; 57 break; 58 #ifdef COMPAT_43 59 case 'o': 60 oflag = 1; 61 break; 62 #endif /* COMPAT_43 */ 63 case '?': 64 default: 65 fprintf(stderr, 66 "usage: df [-ikn] [file | file_system ...]\n"); 67 exit(1); 68 } 69 argc -= optind; 70 argv += optind; 71 72 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 73 maxwidth = 0; 74 for (i = 0; i < mntsize; i++) { 75 width = strlen(mntbuf[i].f_mntfromname); 76 if (width > maxwidth) 77 maxwidth = width; 78 } 79 #ifdef COMPAT_43 80 if (oflag) { 81 olddf(argv, maxwidth); 82 exit(0); 83 } 84 #endif /* COMPAT_43 */ 85 if (!*argv) { 86 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT)); 87 for (i = 0; i < mntsize; i++) 88 prtstat(&mntbuf[i], maxwidth); 89 exit(0); 90 } 91 for (; *argv; argv++) { 92 if (stat(*argv, &stbuf) < 0) { 93 err = errno; 94 if ((mntpt = getmntpt(*argv)) == 0) { 95 fprintf(stderr, "df: %s: %s\n", *argv, 96 strerror(err)); 97 continue; 98 } 99 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) { 100 if ((mntpt = getmntpt(*argv)) == 0) { 101 mntpt = mktemp("/tmp/df.XXXXXX"); 102 mdev.fspec = *argv; 103 if (!mkdir(mntpt) && 104 !mount(MOUNT_UFS, mntpt, MNT_RDONLY, &mdev) && 105 !statfs(mntpt, &statfsbuf)) { 106 statfsbuf.f_mntonname[0] = '\0'; 107 prtstat(&statfsbuf, maxwidth); 108 } else 109 fprintf(stderr, "df: %s: %s\n", 110 *argv, strerror(errno)); 111 (void)unmount(mntpt, MNT_NOFORCE); 112 (void)rmdir(mntpt); 113 continue; 114 } 115 } else 116 mntpt = *argv; 117 /* 118 * Statfs does not take a `wait' flag, so we cannot 119 * implement nflag here. 120 */ 121 if (statfs(mntpt, &statfsbuf) < 0) { 122 fprintf(stderr, 123 "df: %s: %s\n", mntpt, strerror(errno)); 124 continue; 125 } 126 if (argc == 1) 127 maxwidth = strlen(statfsbuf.f_mntfromname) + 1; 128 prtstat(&statfsbuf, maxwidth); 129 } 130 exit(0); 131 } 132 133 char * 134 getmntpt(name) 135 char *name; 136 { 137 long mntsize, i; 138 struct statfs *mntbuf; 139 140 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT)); 141 for (i = 0; i < mntsize; i++) { 142 if (!strcmp(mntbuf[i].f_mntfromname, name)) 143 return (mntbuf[i].f_mntonname); 144 } 145 return (0); 146 } 147 148 /* 149 * Print out status about a filesystem. 150 */ 151 prtstat(sfsp, maxwidth) 152 register struct statfs *sfsp; 153 long maxwidth; 154 { 155 long used, availblks, inodes; 156 static int timesthrough; 157 158 if (maxwidth < 11) 159 maxwidth = 11; 160 if (++timesthrough == 1) { 161 printf("%-*.*s%s used avail capacity", 162 maxwidth, maxwidth, "Filesystem", 163 kflag ? " kbytes" : "512-blks"); 164 if (iflag) 165 printf(" iused ifree %%iused"); 166 printf(" Mounted on\n"); 167 } 168 printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname); 169 used = sfsp->f_blocks - sfsp->f_bfree; 170 availblks = sfsp->f_bavail + used; 171 printf("%8ld%8ld%8ld", 172 sfsp->f_blocks * sfsp->f_fsize / (kflag ? 1024 : 512), 173 used * sfsp->f_fsize / (kflag ? 1024 : 512), 174 sfsp->f_bavail * sfsp->f_fsize / (kflag ? 1024 : 512)); 175 printf("%6.0f%%", 176 availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); 177 if (iflag) { 178 inodes = sfsp->f_files; 179 used = inodes - sfsp->f_ffree; 180 printf("%8ld%8ld%6.0f%% ", used, sfsp->f_ffree, 181 inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0); 182 } else 183 printf(" "); 184 printf(" %s\n", sfsp->f_mntonname); 185 } 186 187 #ifdef COMPAT_43 188 /* 189 * This code constitutes the old df code for extracting 190 * information from filesystem superblocks. 191 */ 192 #include <ufs/fs.h> 193 #include <errno.h> 194 #include <fstab.h> 195 196 char root[MAXPATHLEN]; 197 198 union { 199 struct fs iu_fs; 200 char dummy[SBSIZE]; 201 } sb; 202 #define sblock sb.iu_fs 203 204 int fi; 205 char *strcpy(); 206 207 olddf(argv, maxwidth) 208 char *argv[]; 209 long maxwidth; 210 { 211 struct fstab *fsp; 212 213 sync(); 214 if (!*argv) { 215 if (setfsent() == 0) 216 perror(_PATH_FSTAB), exit(1); 217 while (fsp = getfsent()) { 218 if (strcmp(fsp->fs_type, FSTAB_RW) && 219 strcmp(fsp->fs_type, FSTAB_RO) && 220 strcmp(fsp->fs_type, FSTAB_RQ)) 221 continue; 222 if (root[0] == 0) 223 (void) strcpy(root, fsp->fs_spec); 224 dfree(fsp->fs_spec, 1, maxwidth); 225 } 226 (void)endfsent(); 227 exit(0); 228 } 229 while (*argv) 230 dfree(*argv++, 0, maxwidth); 231 exit(0); 232 } 233 234 dfree(file, infsent, maxwidth) 235 char *file; 236 int infsent; 237 long maxwidth; 238 { 239 extern int errno; 240 struct stat stbuf; 241 struct statfs statfsbuf; 242 register struct statfs *sfsp; 243 struct fstab *fsp; 244 char *mntpt; 245 246 if (stat(file, &stbuf) == 0 && 247 (stbuf.st_mode&S_IFMT) != S_IFCHR && 248 (stbuf.st_mode&S_IFMT) != S_IFBLK) { 249 if (infsent) { 250 fprintf(stderr, "df: %s: screwy fstab entry\n", file); 251 return; 252 } 253 (void)setfsent(); 254 while (fsp = getfsent()) { 255 struct stat stb; 256 257 if (stat(fsp->fs_spec, &stb) == 0 && 258 stb.st_rdev == stbuf.st_dev) { 259 file = fsp->fs_spec; 260 (void)endfsent(); 261 goto found; 262 } 263 } 264 (void)endfsent(); 265 fprintf(stderr, "df: %s: mounted on unknown device\n", file); 266 return; 267 } 268 found: 269 if ((fi = open(file, O_RDONLY)) < 0) { 270 fprintf(stderr, "df: %s: %s\n", file, strerror(errno)); 271 return; 272 } 273 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) { 274 (void) close(fi); 275 return; 276 } 277 sfsp = &statfsbuf; 278 sfsp->f_type = MOUNT_UFS; 279 sfsp->f_flags = 0; 280 sfsp->f_fsize = sblock.fs_fsize; 281 sfsp->f_bsize = sblock.fs_bsize; 282 sfsp->f_blocks = sblock.fs_dsize; 283 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + 284 sblock.fs_cstotal.cs_nffree; 285 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) - 286 (sblock.fs_dsize - sfsp->f_bfree); 287 if (sfsp->f_bavail < 0) 288 sfsp->f_bavail = 0; 289 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg; 290 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree; 291 sfsp->f_fsid.val[0] = 0; 292 sfsp->f_fsid.val[1] = 0; 293 if ((mntpt = getmntpt(file)) == 0) 294 mntpt = ""; 295 bcopy((caddr_t)mntpt, (caddr_t)&sfsp->f_mntonname[0], MNAMELEN); 296 bcopy((caddr_t)file, (caddr_t)&sfsp->f_mntfromname[0], MNAMELEN); 297 prtstat(sfsp, maxwidth); 298 (void) close(fi); 299 } 300 301 long lseek(); 302 303 bread(off, buf, cnt) 304 long off; 305 char *buf; 306 { 307 int n; 308 extern errno; 309 310 (void) lseek(fi, off, SEEK_SET); 311 if ((n=read(fi, buf, cnt)) != cnt) { 312 /* probably a dismounted disk if errno == EIO */ 313 if (errno != EIO) { 314 printf("\nread error off = %ld\n", off); 315 printf("count = %d; errno = %d\n", n, errno); 316 } 317 return (0); 318 } 319 return (1); 320 } 321 #endif /* COMPAT_43 */ 322