1 /* df - disk free block printout Author: Andy Tanenbaum
3 * 91/04/30 Kees J. Bot (kjb@cs.vu.nl)
4 * Map filename arguments to the devices they live on.
5 * Changed output to show percentages.
8 * Posixized. (Almost, the normal output is in kilobytes, it should
9 * be 512-byte units. 'df -P' and 'df -kP' are as it should be.)
14 #include <sys/types.h>
15 #include <sys/statvfs.h>
21 #include <minix/minlib.h>
23 struct mtab
{ /* List of mounted devices from /etc/mtab. */
30 struct mtab
*searchtab(char *name
);
31 static void readmtab(const char *type
);
32 int df(const struct mtab
*mt
);
34 int iflag
= 0; /* Focus on inodes instead of blocks. */
35 int Pflag
= 0; /* Posix standard output. */
36 int kflag
= 0; /* Output in kilobytes instead of 512 byte units for -P. */
37 int istty
; /* isatty(1) */
41 fprintf(stderr
, "Usage: df [-ikP] [-t type] [device]...\n");
47 int main(int argc
, char *argv
[])
54 while (argc
> 1 && argv
[1][0] == '-') {
59 case 'i': iflag
= 1; break;
60 case 'k': kflag
= 1; break;
61 case 'P': Pflag
= 1; break;
63 if (argc
< 3) usage();
80 if(!Pflag
|| (Pflag
&& kflag
)) unitsize
= 1024;
86 Filesystem %4d-blocks Used Available Capacity Mounted on\n",
90 Filesystem Inodes IUsed IFree %%IUsed Mounted on\n"
93 printf("%s\n", !iflag
? "\
94 Filesystem Size (kB) Free Used % Files% Mounted on" : "\
95 Filesystem Files Free Used % BUsed% Mounted on"
100 for (mt
= mtab
; mt
!= NULL
; mt
= mt
->next
) ex
|= df(mt
);
102 for (i
= 1; i
< argc
; i
++) ex
|= df(searchtab(argv
[i
]));
107 static void readmtab(const char *type
)
108 /* Turn the mounted file table into a list. */
110 struct mtab
**amt
= &mtab
, *new;
112 char devname
[PATH_MAX
], mountpoint
[PATH_MAX
], version
[MNTNAMELEN
],
115 if (load_mtab("df") < 0) exit(1);
117 while (get_mtab_entry(devname
, mountpoint
, version
, rw_flag
),
119 if (strcmp(type
, "dev") != 0 && strcmp(type
, version
) != 0) continue;
121 /* Make new list cell. */
122 if ((new= (struct mtab
*) malloc(sizeof(*new))) == NULL
123 || (new->devname
= (char *) malloc(strlen(devname
) + 1)) == NULL
124 || (new->mountpoint
= (char *) malloc(strlen(mountpoint
) + 1)) == NULL
127 if (strcmp(devname
, "none") != 0 && stat(devname
, &st
) == 0 &&
128 S_ISBLK(st
.st_mode
)) {
129 new->device
= st
.st_rdev
;
130 } else if (stat(mountpoint
, &st
) == 0) {
131 new->device
= st
.st_dev
;
133 strcpy(new->devname
, devname
);
134 strcpy(new->mountpoint
, mountpoint
);
136 *amt
= new; /* Add the cell to the end. */
142 struct mtab
*searchtab(char *name
)
143 /* See what we can do with a user supplied name, there are three possibilities:
144 * 1. It's a device and it is in the mtab: Return mtab entry.
145 * 2. It's a file and lives on a device in the mtab: Return mtab entry.
146 * 3. It's anything else: Return something df() will choke on.
149 static struct mtab unknown
;
153 unknown
.devname
= name
;
154 unknown
.mountpoint
= "";
156 if (stat(name
, &st
) < 0) return &unknown
; /* Case 3. */
158 unknown
.device
= S_ISBLK(st
.st_mode
) ? st
.st_rdev
: st
.st_dev
;
160 for (mt
= mtab
; mt
!= NULL
; mt
= mt
->next
) {
161 if (unknown
.device
== mt
->device
)
162 return mt
; /* Case 1 & 2. */
165 return &unknown
; /* Case 3. */
168 /* (num / tot) in percentages rounded up. */
169 #define percent(num, tot) \
170 ((tot > 0) ? ((int) ((100ULL * (num) + ((tot) - 1)) / (tot))) : 0)
172 int df(const struct mtab
*mt
)
174 long totblocks
, busyblocks
, totinodes
, busyinodes
;
178 if (statvfs(mt
->mountpoint
, &sv
) < 0) {
179 fprintf(stderr
, "df: %s: %s\n", mt
->devname
, strerror(errno
));
184 printf("%s", mt
->devname
);
185 n
= strlen(mt
->devname
);
186 if (n
> 15 && istty
) { putchar('\n'); n
= 0; }
187 while (n
< 15) { putchar(' '); n
++; }
189 totblocks
= sv
.f_blocks
;
190 busyblocks
= sv
.f_blocks
- sv
.f_bfree
;
192 busyblocks
= busyblocks
* (sv
.f_bsize
/512) / (unitsize
/512);
193 totblocks
= totblocks
* (sv
.f_bsize
/512) / (unitsize
/512);
195 totinodes
= sv
.f_files
;
196 busyinodes
= sv
.f_files
- sv
.f_ffree
;
198 if (!Pflag
&& !iflag
) {
199 printf(" %9ld %9ld %9ld %3d%% %3d%% %s\n",
200 totblocks
, /* Blocks */
201 totblocks
- busyblocks
, /* free */
202 busyblocks
, /* used */
203 percent(busyblocks
, totblocks
), /* % */
204 percent(busyinodes
, totinodes
), /* FUsed% */
205 mt
->mountpoint
/* Mounted on */
208 if (!Pflag
&& iflag
) {
209 printf(" %9ld %9ld %9ld %3d%% %3d%% %s\n",
210 totinodes
, /* Files */
211 totinodes
- busyinodes
, /* free */
212 busyinodes
, /* used */
213 percent(busyinodes
, totinodes
), /* % */
214 percent(busyblocks
, totblocks
), /* BUsed% */
215 mt
->mountpoint
/* Mounted on */
218 if (Pflag
&& !iflag
) {
219 printf(" %9ld %9ld %9ld %4d%% %s\n",
220 totblocks
, /* Blocks */
221 busyblocks
, /* Used */
222 totblocks
- busyblocks
, /* Available */
223 percent(busyblocks
, totblocks
), /* Capacity */
224 mt
->mountpoint
/* Mounted on */
227 if (Pflag
&& iflag
) {
228 printf(" %9ld %9ld %9ld %4d%% %s\n",
229 totinodes
, /* Inodes */
230 busyinodes
, /* IUsed */
231 totinodes
- busyinodes
, /* IAvail */
232 percent(busyinodes
, totinodes
), /* Capacity */
233 mt
->mountpoint
/* Mounted on */