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