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.33 (Berkeley) 04/28/93"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/stat.h> 20 #include <sys/mount.h> 21 22 #include <err.h> 23 #include <errno.h> 24 #include <fcntl.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 int bread __P((off_t, void *, int)); 31 char *getbsize __P((char *, int *, long *)); 32 char *getmntpt __P((char *)); 33 void prtstat __P((struct statfs *, int)); 34 void ufs_df __P((char *, int)); 35 void usage __P((void)); 36 37 int iflag, nflag; 38 struct ufs_args mdev; 39 40 int 41 main(argc, argv) 42 int argc; 43 char *argv[]; 44 { 45 struct stat stbuf; 46 struct statfs statfsbuf, *mntbuf; 47 long mntsize; 48 int err, ch, i, maxwidth, width; 49 char *mntpt; 50 51 while ((ch = getopt(argc, argv, "in")) != EOF) 52 switch(ch) { 53 case 'i': 54 iflag = 1; 55 break; 56 case 'n': 57 nflag = 1; 58 break; 59 case '?': 60 default: 61 usage(); 62 } 63 argc -= optind; 64 argv += optind; 65 66 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 67 maxwidth = 0; 68 for (i = 0; i < mntsize; i++) { 69 width = strlen(mntbuf[i].f_mntfromname); 70 if (width > maxwidth) 71 maxwidth = width; 72 } 73 if (!*argv) { 74 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT)); 75 for (i = 0; i < mntsize; i++) 76 prtstat(&mntbuf[i], maxwidth); 77 exit(0); 78 } 79 for (; *argv; argv++) { 80 if (stat(*argv, &stbuf) < 0) { 81 err = errno; 82 if ((mntpt = getmntpt(*argv)) == 0) { 83 warn("%s", *argv); 84 continue; 85 } 86 } else if ((stbuf.st_mode & S_IFMT) == S_IFCHR) { 87 ufs_df(*argv, maxwidth); 88 continue; 89 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) { 90 if ((mntpt = getmntpt(*argv)) == 0) { 91 mntpt = mktemp(strdup("/tmp/df.XXXXXX")); 92 mdev.fspec = *argv; 93 if (mkdir(mntpt, DEFFILEMODE) != 0) { 94 warn("%s", mntpt); 95 continue; 96 } 97 if (mount(MOUNT_UFS, mntpt, MNT_RDONLY, 98 &mdev) != 0) { 99 ufs_df(*argv, maxwidth); 100 (void)rmdir(mntpt); 101 continue; 102 } else if (statfs(mntpt, &statfsbuf)) { 103 statfsbuf.f_mntonname[0] = '\0'; 104 prtstat(&statfsbuf, maxwidth); 105 } else 106 warn("%s", *argv); 107 (void)unmount(mntpt, 0); 108 (void)rmdir(mntpt); 109 continue; 110 } 111 } else 112 mntpt = *argv; 113 /* 114 * Statfs does not take a `wait' flag, so we cannot 115 * implement nflag here. 116 */ 117 if (statfs(mntpt, &statfsbuf) < 0) { 118 warn("%s", mntpt); 119 continue; 120 } 121 if (argc == 1) 122 maxwidth = strlen(statfsbuf.f_mntfromname) + 1; 123 prtstat(&statfsbuf, maxwidth); 124 } 125 return (0); 126 } 127 128 char * 129 getmntpt(name) 130 char *name; 131 { 132 long mntsize, i; 133 struct statfs *mntbuf; 134 135 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT)); 136 for (i = 0; i < mntsize; i++) { 137 if (!strcmp(mntbuf[i].f_mntfromname, name)) 138 return (mntbuf[i].f_mntonname); 139 } 140 return (0); 141 } 142 143 /* 144 * Print out status about a filesystem. 145 */ 146 void 147 prtstat(sfsp, maxwidth) 148 register struct statfs *sfsp; 149 int maxwidth; 150 { 151 static long blocksize; 152 static int headerlen, timesthrough; 153 static char *header; 154 long used, availblks, inodes; 155 156 if (maxwidth < 11) 157 maxwidth = 11; 158 if (++timesthrough == 1) { 159 header = getbsize("df", &headerlen, &blocksize); 160 (void)printf("%-*.*s %s Used Avail Capacity", 161 maxwidth, maxwidth, "Filesystem", header); 162 if (iflag) 163 (void)printf(" iused ifree %%iused"); 164 (void)printf(" Mounted on\n"); 165 } 166 (void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname); 167 used = sfsp->f_blocks - sfsp->f_bfree; 168 availblks = sfsp->f_bavail + used; 169 (void)printf(" %*ld %7ld %7ld", headerlen, 170 sfsp->f_blocks * sfsp->f_bsize / blocksize, 171 used * sfsp->f_bsize / blocksize, 172 sfsp->f_bavail * sfsp->f_bsize / blocksize); 173 (void)printf(" %5.0f%%", 174 availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); 175 if (iflag) { 176 inodes = sfsp->f_files; 177 used = inodes - sfsp->f_ffree; 178 (void)printf(" %7ld %7ld %5.0f%% ", used, sfsp->f_ffree, 179 inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0); 180 } else 181 (void)printf(" "); 182 (void)printf(" %s\n", sfsp->f_mntonname); 183 } 184 185 /* 186 * This code constitutes the pre-system call Berkeley df code for extracting 187 * information from filesystem superblocks. 188 */ 189 #include <ufs/ffs/fs.h> 190 #include <errno.h> 191 #include <fstab.h> 192 193 union { 194 struct fs iu_fs; 195 char dummy[SBSIZE]; 196 } sb; 197 #define sblock sb.iu_fs 198 199 int rfd; 200 201 void 202 ufs_df(file, maxwidth) 203 char *file; 204 int maxwidth; 205 { 206 struct statfs statfsbuf; 207 register struct statfs *sfsp; 208 char *mntpt; 209 static int synced; 210 211 if (synced++ == 0) 212 sync(); 213 214 if ((rfd = open(file, O_RDONLY)) < 0) { 215 warn("%s", file); 216 return; 217 } 218 if (bread((off_t)SBOFF, &sblock, SBSIZE) == 0) { 219 (void)close(rfd); 220 return; 221 } 222 sfsp = &statfsbuf; 223 sfsp->f_type = MOUNT_UFS; 224 sfsp->f_flags = 0; 225 sfsp->f_bsize = sblock.fs_fsize; 226 sfsp->f_iosize = sblock.fs_bsize; 227 sfsp->f_blocks = sblock.fs_dsize; 228 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + 229 sblock.fs_cstotal.cs_nffree; 230 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) - 231 (sblock.fs_dsize - sfsp->f_bfree); 232 if (sfsp->f_bavail < 0) 233 sfsp->f_bavail = 0; 234 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg; 235 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree; 236 sfsp->f_fsid.val[0] = 0; 237 sfsp->f_fsid.val[1] = 0; 238 if ((mntpt = getmntpt(file)) == 0) 239 mntpt = ""; 240 memmove(&sfsp->f_mntonname[0], mntpt, MNAMELEN); 241 memmove(&sfsp->f_mntfromname[0], file, MNAMELEN); 242 prtstat(sfsp, maxwidth); 243 (void)close(rfd); 244 } 245 246 int 247 bread(off, buf, cnt) 248 off_t off; 249 void *buf; 250 int cnt; 251 { 252 int nr; 253 254 (void)lseek(rfd, off, SEEK_SET); 255 if ((nr = read(rfd, buf, cnt)) != cnt) { 256 /* Probably a dismounted disk if errno == EIO. */ 257 if (errno != EIO) 258 (void)fprintf(stderr, "\ndf: %qd: %s\n", 259 off, strerror(nr > 0 ? EIO : errno)); 260 return (0); 261 } 262 return (1); 263 } 264 265 void 266 usage() 267 { 268 (void)fprintf(stderr, "usage: df [-in] [file | file_system ...]\n"); 269 exit(1); 270 } 271