1 /* 2 * Copyright (c) 1980, 1990 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, 1990 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.30 (Berkeley) 04/23/92"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/stat.h> 20 #include <sys/mount.h> 21 #include <errno.h> 22 #include <fcntl.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 int bread __P((long, char *, int)); 29 char *getbsize __P((char *, int *, long *)); 30 char *getmntpt __P((char *)); 31 void prtstat __P((struct statfs *, long)); 32 void ufs_df __P((char *, long)); 33 void usage __P((void)); 34 35 int iflag, nflag; 36 struct ufs_args mdev; 37 38 int 39 main(argc, argv) 40 int argc; 41 char *argv[]; 42 { 43 struct stat stbuf; 44 struct statfs statfsbuf, *mntbuf; 45 long width, maxwidth, mntsize; 46 int err, ch, i; 47 char *mntpt; 48 49 while ((ch = getopt(argc, argv, "ikn")) != EOF) 50 switch(ch) { 51 case 'i': 52 iflag = 1; 53 break; 54 case 'k': /* Delete before 4.4BSD. */ 55 (void)fprintf(stderr, "df: -k no longer supported\n"); 56 break; 57 case 'n': 58 nflag = 1; 59 break; 60 case '?': 61 default: 62 usage(); 63 } 64 argc -= optind; 65 argv += optind; 66 67 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 68 maxwidth = 0; 69 for (i = 0; i < mntsize; i++) { 70 width = strlen(mntbuf[i].f_mntfromname); 71 if (width > maxwidth) 72 maxwidth = width; 73 } 74 if (!*argv) { 75 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT)); 76 for (i = 0; i < mntsize; i++) 77 prtstat(&mntbuf[i], maxwidth); 78 exit(0); 79 } 80 for (; *argv; argv++) { 81 if (stat(*argv, &stbuf) < 0) { 82 err = errno; 83 if ((mntpt = getmntpt(*argv)) == 0) { 84 fprintf(stderr, "df: %s: %s\n", *argv, 85 strerror(err)); 86 continue; 87 } 88 } else if ((stbuf.st_mode & S_IFMT) == S_IFCHR) { 89 ufs_df(*argv, maxwidth); 90 continue; 91 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) { 92 if ((mntpt = getmntpt(*argv)) == 0) { 93 mntpt = mktemp(strdup("/tmp/df.XXXXXX")); 94 mdev.fspec = *argv; 95 if (mkdir(mntpt, DEFFILEMODE) != 0) { 96 fprintf(stderr, "df: %s: %s\n", 97 mntpt, strerror(errno)); 98 continue; 99 } 100 if (mount(MOUNT_UFS, mntpt, MNT_RDONLY, 101 &mdev) != 0) { 102 ufs_df(*argv, maxwidth); 103 (void)rmdir(mntpt); 104 continue; 105 } else if (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 return (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 void 152 prtstat(sfsp, maxwidth) 153 register struct statfs *sfsp; 154 long maxwidth; 155 { 156 static long blocksize; 157 static int headerlen, timesthrough; 158 static char *header; 159 long used, availblks, inodes; 160 161 if (maxwidth < 11) 162 maxwidth = 11; 163 if (++timesthrough == 1) { 164 header = getbsize("df", &headerlen, &blocksize); 165 (void)printf("%-*.*s %s Used Avail Capacity", 166 maxwidth, maxwidth, "Filesystem", header); 167 if (iflag) 168 (void)printf(" iused ifree %%iused"); 169 (void)printf(" Mounted on\n"); 170 } 171 (void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname); 172 used = sfsp->f_blocks - sfsp->f_bfree; 173 availblks = sfsp->f_bavail + used; 174 (void)printf(" %*ld %7ld %7ld", headerlen, 175 sfsp->f_blocks * sfsp->f_bsize / blocksize, 176 used * sfsp->f_bsize / blocksize, 177 sfsp->f_bavail * sfsp->f_bsize / blocksize); 178 (void)printf(" %5.0f%%", 179 availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); 180 if (iflag) { 181 inodes = sfsp->f_files; 182 used = inodes - sfsp->f_ffree; 183 (void)printf(" %7ld %7ld %5.0f%% ", used, sfsp->f_ffree, 184 inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0); 185 } else 186 (void)printf(" "); 187 (void)printf(" %s\n", sfsp->f_mntonname); 188 } 189 190 /* 191 * This code constitutes the old df code for extracting 192 * information from filesystem superblocks. 193 */ 194 #include <ufs/ffs/fs.h> 195 #include <errno.h> 196 #include <fstab.h> 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 206 void 207 ufs_df(file, maxwidth) 208 char *file; 209 long maxwidth; 210 { 211 struct statfs statfsbuf; 212 register struct statfs *sfsp; 213 char *mntpt; 214 static int synced; 215 216 if (synced++ == 0) 217 sync(); 218 219 if ((fi = open(file, O_RDONLY)) < 0) { 220 (void)fprintf(stderr, "df: %s: %s\n", file, strerror(errno)); 221 return; 222 } 223 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) { 224 (void)close(fi); 225 return; 226 } 227 sfsp = &statfsbuf; 228 sfsp->f_type = MOUNT_UFS; 229 sfsp->f_flags = 0; 230 sfsp->f_bsize = sblock.fs_fsize; 231 sfsp->f_iosize = sblock.fs_bsize; 232 sfsp->f_blocks = sblock.fs_dsize; 233 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + 234 sblock.fs_cstotal.cs_nffree; 235 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) - 236 (sblock.fs_dsize - sfsp->f_bfree); 237 if (sfsp->f_bavail < 0) 238 sfsp->f_bavail = 0; 239 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg; 240 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree; 241 sfsp->f_fsid.val[0] = 0; 242 sfsp->f_fsid.val[1] = 0; 243 if ((mntpt = getmntpt(file)) == 0) 244 mntpt = ""; 245 bcopy((caddr_t)mntpt, (caddr_t)&sfsp->f_mntonname[0], MNAMELEN); 246 bcopy((caddr_t)file, (caddr_t)&sfsp->f_mntfromname[0], MNAMELEN); 247 prtstat(sfsp, maxwidth); 248 (void) close(fi); 249 } 250 251 int 252 bread(off, buf, cnt) 253 long off; 254 char *buf; 255 int cnt; 256 { 257 int n; 258 259 (void) lseek(fi, off, SEEK_SET); 260 if ((n=read(fi, buf, cnt)) != cnt) { 261 /* probably a dismounted disk if errno == EIO */ 262 if (errno != EIO) { 263 (void)printf("\nread error off = %ld\n", off); 264 (void)printf("count = %d: %s\n", n, strerror(errno)); 265 } 266 return (0); 267 } 268 return (1); 269 } 270 271 void 272 usage() 273 { 274 (void)fprintf(stderr, "usage: df [-in] [file | file_system ...]\n"); 275 exit(1); 276 } 277