00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <sys/types.h>
00015 #include <sys/stat.h>
00016 #include <limits.h>
00017 #include <fcntl.h>
00018 #include <errno.h>
00019 #include <unistd.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <dirent.h>
00024 #if __minix_vmd
00025 #include <sys/mnttab.h>
00026 #else
00027 #include <minix/minlib.h>
00028 #endif
00029
00030 #include <minix/config.h>
00031 #include <minix/const.h>
00032 #include <minix/type.h>
00033 #include <servers/fs/const.h>
00034 #include <servers/fs/type.h>
00035 #include <servers/fs/super.h>
00036 #undef printf
00037
00038 #if !__minix_vmd
00039
00040 #define v12_super_block super_block
00041 #define SUPER_V1 SUPER_MAGIC
00042
00043 #endif
00044
00045 #define ISDISK(mode) S_ISBLK(mode)
00046
00047 extern int errno;
00048 char MTAB[] = "/etc/mtab";
00049
00050 struct mtab {
00051 struct mtab *next;
00052 dev_t device;
00053 char *devname;
00054 char *mountpoint;
00055 } *mtab= NULL;
00056
00057 struct mtab *searchtab(char *name);
00058 void readmtab(char *type);
00059 int df(const struct mtab *mt);
00060 bit_t bit_count(unsigned blocks, bit_t bits, int fd, int bs);
00061
00062 int iflag= 0;
00063 int Pflag= 0;
00064 int kflag= 0;
00065 int istty;
00066 uid_t ruid, euid;
00067 gid_t rgid, egid;
00068
00069 void usage(void)
00070 {
00071 fprintf(stderr, "Usage: df [-ikP] [-t type] [device]...\n");
00072 exit(1);
00073 }
00074
00075 int unitsize;
00076
00077 int main(int argc, char *argv[])
00078 {
00079 int i;
00080 struct mtab *mt;
00081 char *type= "dev";
00082 int ex= 0;
00083
00084 while (argc > 1 && argv[1][0] == '-') {
00085 char *opt= argv[1]+1;
00086
00087 while (*opt != 0) {
00088 switch (*opt++) {
00089 case 'i': iflag= 1; break;
00090 case 'k': kflag= 1; break;
00091 case 'P': Pflag= 1; break;
00092 case 't':
00093 if (argc < 3) usage();
00094 type= argv[2];
00095 argv++;
00096 argc--;
00097 break;
00098 default:
00099 usage();
00100 }
00101 }
00102 argc--;
00103 argv++;
00104 }
00105
00106 istty= isatty(1);
00107 ruid= getuid(); euid= geteuid();
00108 rgid= getgid(); egid= getegid();
00109
00110 readmtab(type);
00111
00112 if(!Pflag || (Pflag && kflag)) unitsize = 1024;
00113 else unitsize = 512;
00114
00115 if (Pflag) {
00116 printf(!iflag ? "\
00117 Filesystem %4d-blocks Used Available Capacity Mounted on\n" : "\
00118 Filesystem Inodes IUsed IFree %%IUsed Mounted on\n",
00119 unitsize);
00120 } else {
00121 printf("%s\n", !iflag ? "\
00122 Filesystem Size (kB) Free Used % Files% Mounted on" : "\
00123 Filesystem Files Free Used % BUsed% Mounted on"
00124 );
00125 }
00126
00127 if (argc == 1) {
00128 for (mt= mtab; mt != NULL; mt= mt->next) ex |= df(mt);
00129 } else {
00130 for (i = 1; i < argc; i++) ex |= df(searchtab(argv[i]));
00131 }
00132 exit(ex);
00133 }
00134
00135 void readmtab(char *type)
00136
00137 {
00138 struct mtab **amt= &mtab, *new;
00139 struct stat st;
00140
00141 #if __minix_vmd
00142 char *devname, *mountpoint;
00143 FILE *mtf;
00144 struct mnttab mte, look;
00145
00146 if ((mtf= fopen(MTAB, "r")) == NULL) {
00147 fprintf(stderr, "df: can't open %s\n", MTAB);
00148 return;
00149 }
00150
00151 look.mnt_special= NULL;
00152 look.mnt_mountp= NULL;
00153 look.mnt_fstype= type;
00154 look.mnt_mntopts= NULL;
00155
00156 while (getmntany(mtf, &mte, &look) >= 0) {
00157 devname= mte.mnt_special;
00158 mountpoint= mte.mnt_mountp;
00159
00160
00161 if (stat(devname, &st) < 0 || !ISDISK(st.st_mode)) continue;
00162
00163
00164 if ((new= (struct mtab *) malloc(sizeof(*new))) == NULL
00165 || (new->devname= (char *) malloc(strlen(devname) + 1)) == NULL
00166 || (new->mountpoint= (char *) malloc(strlen(mountpoint) + 1)) == NULL
00167 ) break;
00168
00169 new->device= st.st_rdev;
00170 strcpy(new->devname, devname);
00171 strcpy(new->mountpoint, mountpoint);
00172
00173 *amt= new;
00174 amt= &new->next;
00175 *amt= NULL;
00176 }
00177 fclose(mtf);
00178
00179 #else
00180 char devname[128], mountpoint[128], version[10], rw_flag[10];
00181
00182 if (load_mtab("df") < 0) exit(1);
00183
00184 while (get_mtab_entry(devname, mountpoint, version, rw_flag),
00185 devname[0] != 0) {
00186 if (strcmp(type, "dev") == 0) {
00187 if (strcmp(version, "1") != 0 && strcmp(version, "2") != 0 &&
00188 strcmp(version, "3"))
00189 continue;
00190 } else {
00191 if (strcmp(type, version) != 0) continue;
00192 }
00193
00194
00195 if (stat(devname, &st) < 0 || !ISDISK(st.st_mode)) continue;
00196
00197
00198 if ((new= (struct mtab *) malloc(sizeof(*new))) == NULL
00199 || (new->devname= (char *) malloc(strlen(devname) + 1)) == NULL
00200 || (new->mountpoint= (char *) malloc(strlen(mountpoint) + 1)) == NULL
00201 ) break;
00202
00203 new->device= st.st_rdev;
00204 strcpy(new->devname, devname);
00205 strcpy(new->mountpoint, mountpoint);
00206
00207 *amt= new;
00208 amt= &new->next;
00209 *amt= NULL;
00210 }
00211 #endif
00212 }
00213
00214 struct mtab *searchtab(char *name)
00215
00216
00217
00218
00219
00220
00221
00222
00223 {
00224 static struct mtab unknown;
00225 static char devname[5 + NAME_MAX + 1]= "/dev/";
00226 struct mtab *mt;
00227 struct stat st;
00228 DIR *dp;
00229 struct dirent *ent;
00230
00231 unknown.devname= name;
00232 unknown.mountpoint= "";
00233
00234 if (stat(name, &st) < 0) return &unknown;
00235
00236 unknown.device= ISDISK(st.st_mode) ? st.st_rdev : st.st_dev;
00237
00238 for (mt= mtab; mt != NULL; mt= mt->next) {
00239 if (unknown.device == mt->device)
00240 return mt;
00241 }
00242
00243 if (ISDISK(st.st_mode)) {
00244 return &unknown;
00245 }
00246
00247 if ((dp= opendir("/dev")) == NULL) return &unknown;
00248
00249 while ((ent= readdir(dp)) != NULL) {
00250 if (ent->d_name[0] == '.') continue;
00251 strcpy(devname + 5, ent->d_name);
00252 if (stat(devname, &st) >= 0 && ISDISK(st.st_mode)
00253 && unknown.device == st.st_rdev
00254 ) {
00255 unknown.devname= devname;
00256 unknown.mountpoint= "???";
00257 break;
00258 }
00259 }
00260 closedir(dp);
00261 return &unknown;
00262 }
00263
00264
00265 #define percent(num, tot) ((int) ((100L * (num) + ((tot) - 1)) / (tot)))
00266
00267
00268 #define L(n) ((long) (n))
00269
00270 int df(const struct mtab *mt)
00271 {
00272 int fd;
00273 bit_t i_count, z_count;
00274 block_t totblocks, busyblocks;
00275 int n, block_size;
00276 struct v12_super_block super, *sp;
00277
00278
00279 seteuid(*mt->mountpoint == 0 ? ruid : euid);
00280 setegid(*mt->mountpoint == 0 ? rgid : egid);
00281
00282 if ((fd = open(mt->devname, O_RDONLY)) < 0) {
00283 fprintf(stderr, "df: %s: %s\n", mt->devname, strerror(errno));
00284 return(1);
00285 }
00286 lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET);
00287
00288 if (read(fd, (char *) &super, sizeof(super)) != (int) sizeof(super)) {
00289 fprintf(stderr, "df: Can't read super block of %s\n", mt->devname);
00290 close(fd);
00291 return(1);
00292 }
00293
00294 sp = &super;
00295 if (sp->s_magic != SUPER_V1 && sp->s_magic != SUPER_V2
00296 && sp->s_magic != SUPER_V3) {
00297 fprintf(stderr, "df: %s: Not a valid file system\n", mt->devname);
00298 close(fd);
00299 return(1);
00300 }
00301
00302 if(sp->s_magic != SUPER_V3) block_size = _STATIC_BLOCK_SIZE;
00303 else block_size = super.s_block_size;
00304
00305 if(block_size < _MIN_BLOCK_SIZE || block_size > _MAX_BLOCK_SIZE) {
00306 fprintf(stderr, "df: %s: funny block size (%d)\n",
00307 mt->devname, block_size);
00308 close(fd);
00309 return(1);
00310 }
00311
00312 if (sp->s_magic == SUPER_V1) sp->s_zones= sp->s_nzones;
00313
00314 lseek(fd, (off_t) block_size * 2L, SEEK_SET);
00315
00316 i_count = bit_count(sp->s_imap_blocks, (bit_t) (sp->s_ninodes+1),
00317 fd, block_size);
00318
00319 if (i_count == -1) {
00320 fprintf(stderr, "df: Can't find bit maps of %s\n", mt->devname);
00321 close(fd);
00322 return(1);
00323 }
00324 i_count--;
00325
00326
00327
00328
00329 z_count = bit_count(sp->s_zmap_blocks,
00330 (bit_t) (sp->s_zones - (sp->s_firstdatazone - 1)), fd, block_size);
00331
00332 if (z_count == -1) {
00333 fprintf(stderr, "df: Can't find bit maps of %s\n", mt->devname);
00334 close(fd);
00335 return(1);
00336 }
00337
00338 z_count += sp->s_firstdatazone - 1;
00339
00340 #ifdef __minix_vmd
00341 totblocks = sp->s_zones;
00342 busyblocks = z_count;
00343 #else
00344 totblocks = (block_t) sp->s_zones << sp->s_log_zone_size;
00345 busyblocks = (block_t) z_count << sp->s_log_zone_size;
00346 #endif
00347
00348 busyblocks = busyblocks * (block_size/512) / (unitsize/512);
00349 totblocks = totblocks * (block_size/512) / (unitsize/512);
00350
00351
00352 printf("%s", mt->devname);
00353 n= strlen(mt->devname);
00354 if (n > 15 && istty) { putchar('\n'); n= 0; }
00355 while (n < 15) { putchar(' '); n++; }
00356
00357 if (!Pflag && !iflag) {
00358 printf(" %9ld %9ld %9ld %3d%% %3d%% %s\n",
00359 L(totblocks),
00360 L(totblocks - busyblocks),
00361 L(busyblocks),
00362 percent(busyblocks, totblocks),
00363 percent(i_count, sp->s_ninodes),
00364 mt->mountpoint
00365 );
00366 }
00367 if (!Pflag && iflag) {
00368 printf(" %9ld %9ld %9ld %3d%% %3d%% %s\n",
00369 L(sp->s_ninodes),
00370 L(sp->s_ninodes - i_count),
00371 L(i_count),
00372 percent(i_count, sp->s_ninodes),
00373 percent(busyblocks, totblocks),
00374 mt->mountpoint
00375 );
00376 }
00377 if (Pflag && !iflag) {
00378 printf(" %9ld %9ld %9ld %4d%% %s\n",
00379 L(totblocks),
00380 L(busyblocks),
00381 totblocks - busyblocks,
00382 percent(busyblocks, totblocks),
00383 mt->mountpoint
00384 );
00385 }
00386 if (Pflag && iflag) {
00387 printf(" %9ld %9ld %9ld %4d%% %s\n",
00388 L(sp->s_ninodes),
00389 L(i_count),
00390 L(sp->s_ninodes - i_count),
00391 percent(i_count, sp->s_ninodes),
00392 mt->mountpoint
00393 );
00394 }
00395 close(fd);
00396 return(0);
00397 }
00398
00399 bit_t bit_count(unsigned blocks, bit_t bits, int fd, int block_size)
00400 {
00401 char *wptr;
00402 int i, b;
00403 bit_t busy;
00404 char *wlim;
00405 static char buf[_MAX_BLOCK_SIZE];
00406 static char bits_in_char[1 << CHAR_BIT];
00407
00408
00409 if (bits_in_char[1] != 1) {
00410 for (b = (1 << 0); b < (1 << CHAR_BIT); b <<= 1)
00411 for (i = 0; i < (1 << CHAR_BIT); i++)
00412 if (i & b) bits_in_char[i]++;
00413 }
00414
00415
00416 busy = 0;
00417 for (i = 0; i < blocks && bits != 0; i++) {
00418 if (read(fd, buf, block_size) != block_size) return(-1);
00419
00420 wptr = &buf[0];
00421 if (bits >= CHAR_BIT * block_size) {
00422 wlim = &buf[block_size];
00423 bits -= CHAR_BIT * block_size;
00424 } else {
00425 b = bits / CHAR_BIT;
00426 wlim = &buf[b];
00427 bits -= b * CHAR_BIT;
00428 b = *wlim & ((1 << bits) - 1);
00429 busy += bits_in_char[b];
00430 bits = 0;
00431 }
00432
00433
00434 while (wptr != wlim)
00435 busy += bits_in_char[*wptr++ & ((1 << CHAR_BIT) - 1)];
00436 }
00437 return(busy);
00438 }
00439
00440
00441
00442