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.27 (Berkeley) 12/14/91"; 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 *getmntpt __P((char *)); 30 void prtstat __P((struct statfs *, long)); 31 void ufs_df __P((char *, long)); 32 void usage __P((void)); 33 34 int iflag, kflag, nflag; 35 struct ufs_args mdev; 36 37 int 38 main(argc, argv) 39 int argc; 40 char **argv; 41 { 42 struct stat stbuf; 43 struct statfs statfsbuf, *mntbuf; 44 long width, maxwidth, mntsize; 45 int err, ch, i; 46 char *mntpt; 47 48 while ((ch = getopt(argc, argv, "ikn")) != EOF) 49 switch(ch) { 50 case 'i': 51 iflag = 1; 52 break; 53 case 'k': 54 kflag = 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 fprintf(stderr, "df: %s: %s\n", *argv, 84 strerror(err)); 85 continue; 86 } 87 } else if ((stbuf.st_mode & S_IFMT) == S_IFCHR) { 88 ufs_df(*argv, maxwidth); 89 continue; 90 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) { 91 if ((mntpt = getmntpt(*argv)) == 0) { 92 mntpt = mktemp(strdup("/tmp/df.XXXXXX")); 93 mdev.fspec = *argv; 94 if (mkdir(mntpt, DEFFILEMODE) != 0) { 95 fprintf(stderr, "df: %s: %s\n", 96 mntpt, strerror(errno)); 97 continue; 98 } 99 if (mount(MOUNT_UFS, mntpt, MNT_RDONLY, 100 &mdev) != 0) { 101 ufs_df(*argv, maxwidth); 102 (void)rmdir(mntpt); 103 continue; 104 } else if (statfs(mntpt, &statfsbuf)) { 105 statfsbuf.f_mntonname[0] = '\0'; 106 prtstat(&statfsbuf, maxwidth); 107 } else 108 fprintf(stderr, "df: %s: %s\n", 109 *argv, strerror(errno)); 110 (void)unmount(mntpt, MNT_NOFORCE); 111 (void)rmdir(mntpt); 112 continue; 113 } 114 } else 115 mntpt = *argv; 116 /* 117 * Statfs does not take a `wait' flag, so we cannot 118 * implement nflag here. 119 */ 120 if (statfs(mntpt, &statfsbuf) < 0) { 121 fprintf(stderr, 122 "df: %s: %s\n", mntpt, strerror(errno)); 123 continue; 124 } 125 if (argc == 1) 126 maxwidth = strlen(statfsbuf.f_mntfromname) + 1; 127 prtstat(&statfsbuf, maxwidth); 128 } 129 return (0); 130 } 131 132 char * 133 getmntpt(name) 134 char *name; 135 { 136 long mntsize, i; 137 struct statfs *mntbuf; 138 139 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT)); 140 for (i = 0; i < mntsize; i++) { 141 if (!strcmp(mntbuf[i].f_mntfromname, name)) 142 return (mntbuf[i].f_mntonname); 143 } 144 return (0); 145 } 146 147 /* 148 * Print out status about a filesystem. 149 */ 150 void 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 ? "1024-blocks" : " 512-blocks"); 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_bsize / (kflag ? 1024 : 512), 173 used * sfsp->f_bsize / (kflag ? 1024 : 512), 174 sfsp->f_bavail * sfsp->f_bsize / (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 /* 188 * This code constitutes the old df code for extracting 189 * information from filesystem superblocks. 190 */ 191 #include <ufs/ffs/fs.h> 192 #include <errno.h> 193 #include <fstab.h> 194 195 union { 196 struct fs iu_fs; 197 char dummy[SBSIZE]; 198 } sb; 199 #define sblock sb.iu_fs 200 201 int fi; 202 203 void 204 ufs_df(file, maxwidth) 205 char *file; 206 long maxwidth; 207 { 208 extern int errno; 209 struct statfs statfsbuf; 210 register struct statfs *sfsp; 211 char *mntpt; 212 static int synced; 213 214 if (synced++ == 0) 215 sync(); 216 217 if ((fi = open(file, O_RDONLY)) < 0) { 218 fprintf(stderr, "df: %s: %s\n", file, strerror(errno)); 219 return; 220 } 221 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) { 222 (void) close(fi); 223 return; 224 } 225 sfsp = &statfsbuf; 226 sfsp->f_type = MOUNT_UFS; 227 sfsp->f_flags = 0; 228 sfsp->f_bsize = sblock.fs_fsize; 229 sfsp->f_iosize = sblock.fs_bsize; 230 sfsp->f_blocks = sblock.fs_dsize; 231 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + 232 sblock.fs_cstotal.cs_nffree; 233 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) - 234 (sblock.fs_dsize - sfsp->f_bfree); 235 if (sfsp->f_bavail < 0) 236 sfsp->f_bavail = 0; 237 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg; 238 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree; 239 sfsp->f_fsid.val[0] = 0; 240 sfsp->f_fsid.val[1] = 0; 241 if ((mntpt = getmntpt(file)) == 0) 242 mntpt = ""; 243 bcopy((caddr_t)mntpt, (caddr_t)&sfsp->f_mntonname[0], MNAMELEN); 244 bcopy((caddr_t)file, (caddr_t)&sfsp->f_mntfromname[0], MNAMELEN); 245 prtstat(sfsp, maxwidth); 246 (void) close(fi); 247 } 248 249 int 250 bread(off, buf, cnt) 251 long off; 252 char *buf; 253 int cnt; 254 { 255 int n; 256 257 (void) lseek(fi, off, SEEK_SET); 258 if ((n=read(fi, buf, cnt)) != cnt) { 259 /* probably a dismounted disk if errno == EIO */ 260 if (errno != EIO) { 261 printf("\nread error off = %ld\n", off); 262 printf("count = %d; errno = %d\n", n, errno); 263 } 264 return (0); 265 } 266 return (1); 267 } 268 269 void 270 usage() 271 { 272 (void)fprintf(stderr, "usage: df [-ikn] [file | file_system ...]\n"); 273 exit(1); 274 } 275