df.c revision b1aaba1fc8176ac0b7c202a664d2554aa0967116
12896480c4918f2accccb8301bec457a7bff7377eRob Landley/* vi: set sw=4 ts=4:
22896480c4918f2accccb8301bec457a7bff7377eRob Landley *
34f344e356d2c36c4b1df46917eaef25f82ca79a9landley * df.c - report free disk space.
44f344e356d2c36c4b1df46917eaef25f82ca79a9landley *
52896480c4918f2accccb8301bec457a7bff7377eRob Landley * Copyright 2006 Rob Landley <rob@landley.net>
62c226859cfc911c4a1eea009897050a16714aeecRob Landley *
72896480c4918f2accccb8301bec457a7bff7377eRob Landley * See http://www.opengroup.org/onlinepubs/009695399/utilities/df.html
82896480c4918f2accccb8301bec457a7bff7377eRob Landley
955928b1e0a08d84a5cbc50020f0a8c1024f5b6ceRob LandleyUSE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN))
1055928b1e0a08d84a5cbc50020f0a8c1024f5b6ceRob Landley
112896480c4918f2accccb8301bec457a7bff7377eRob Landleyconfig DF
122896480c4918f2accccb8301bec457a7bff7377eRob Landley	bool "df (disk free)"
132896480c4918f2accccb8301bec457a7bff7377eRob Landley	default y
142896480c4918f2accccb8301bec457a7bff7377eRob Landley	help
152896480c4918f2accccb8301bec457a7bff7377eRob Landley	  usage: df [-t type] [FILESYSTEM ...]
162896480c4918f2accccb8301bec457a7bff7377eRob Landley
172896480c4918f2accccb8301bec457a7bff7377eRob Landley	  The "disk free" command, df shows total/used/available disk space for
182896480c4918f2accccb8301bec457a7bff7377eRob Landley	  each filesystem listed on the command line, or all currently mounted
192896480c4918f2accccb8301bec457a7bff7377eRob Landley	  filesystems.
202896480c4918f2accccb8301bec457a7bff7377eRob Landley
212896480c4918f2accccb8301bec457a7bff7377eRob Landley	  -t type
222896480c4918f2accccb8301bec457a7bff7377eRob Landley		Display only filesystems of this type.
232896480c4918f2accccb8301bec457a7bff7377eRob Landley
242896480c4918f2accccb8301bec457a7bff7377eRob Landleyconfig DF_PEDANTIC
252896480c4918f2accccb8301bec457a7bff7377eRob Landley	bool "options -P and -k"
262896480c4918f2accccb8301bec457a7bff7377eRob Landley	default y
272896480c4918f2accccb8301bec457a7bff7377eRob Landley	depends on DF
282896480c4918f2accccb8301bec457a7bff7377eRob Landley	help
292896480c4918f2accccb8301bec457a7bff7377eRob Landley	  usage: df [-Pk]
302896480c4918f2accccb8301bec457a7bff7377eRob Landley
312896480c4918f2accccb8301bec457a7bff7377eRob Landley	  -P	The SUSv3 "Pedantic" option
322896480c4918f2accccb8301bec457a7bff7377eRob Landley
332896480c4918f2accccb8301bec457a7bff7377eRob Landley		Provides a slightly less useful output format dictated by
342896480c4918f2accccb8301bec457a7bff7377eRob Landley		the Single Unix Specification version 3, and sets the
352896480c4918f2accccb8301bec457a7bff7377eRob Landley		units to 512 bytes instead of the default 1024 bytes.
362896480c4918f2accccb8301bec457a7bff7377eRob Landley
372896480c4918f2accccb8301bec457a7bff7377eRob Landley	  -k	Sets units back to 1024 bytes (the default without -P)
382896480c4918f2accccb8301bec457a7bff7377eRob Landley*/
394f344e356d2c36c4b1df46917eaef25f82ca79a9landley
40c56215062c961402515daeef8330ed75cd94af29landley#include "toys.h"
41c56215062c961402515daeef8330ed75cd94af29landley
42b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob LandleyDEFINE_GLOBALS(
43b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley	struct arg_list *fstype;
44b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley
45b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley	long units;
46b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley)
47b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley
48b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley#define TT this.df
49b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley
5009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landleystatic void show_mt(struct mtab_list *mt)
5109ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley{
5209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	int len;
5352fb04274b3491fdfe91b2e5acc23dc3f3064a86landley	long size, used, avail, percent;
5409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	uint64_t block;
5509ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
5609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// Return if it wasn't found (should never happen, but with /etc/mtab...)
5709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	if (!mt) return;
5809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
5909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// If we have -t, skip other filesystem types
60b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley	if (TT.fstype) {
6158c6c1be60d96df4b7cb8d77625948b0da297144Rob Landley		struct arg_list *al;
6209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
63b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley		for (al = TT.fstype; al; al = al->next) {
6458c6c1be60d96df4b7cb8d77625948b0da297144Rob Landley			if (!strcmp(mt->type, al->arg)) break;
6558c6c1be60d96df4b7cb8d77625948b0da297144Rob Landley		}
6658c6c1be60d96df4b7cb8d77625948b0da297144Rob Landley		if (!al) return;
6709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	}
6809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
6909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// If we don't have -a, skip synthetic filesystems
7009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	if (!(toys.optflags & 1) && !mt->statvfs.f_blocks) return;
7109ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
7209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// Figure out how much total/used/free space this filesystem has,
7309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// forcing 64-bit math because filesystems are big now.
7409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	block = mt->statvfs.f_bsize ? : 1;
75b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley	size = (long)((block * mt->statvfs.f_blocks) / TT.units);
7609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	used = (long)((block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree))
77b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley			/ TT.units);
7809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	avail = (long)((block
7909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley				* (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree))
80b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley			/ TT.units);
818324b89598b2aee0957a0378f0f63ff5755498beRob Landley	percent = size ? 100-(long)((100*(uint64_t)avail)/size) : 0;
8209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
8309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// Figure out appropriate spacing
8409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	len = 25 - strlen(mt->device);
8509ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	if (len < 1) len = 1;
8652fb04274b3491fdfe91b2e5acc23dc3f3064a86landley	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
8752fb04274b3491fdfe91b2e5acc23dc3f3064a86landley		printf("%s %ld %ld %ld %ld%% %s\n", mt->device, size, used, avail,
8852fb04274b3491fdfe91b2e5acc23dc3f3064a86landley				percent, mt->dir);
8952fb04274b3491fdfe91b2e5acc23dc3f3064a86landley	} else {
9052fb04274b3491fdfe91b2e5acc23dc3f3064a86landley		printf("%s% *ld % 10ld % 9ld % 3ld%% %s\n",mt->device, len,
9152fb04274b3491fdfe91b2e5acc23dc3f3064a86landley			size, used, avail, percent, mt->dir);
9252fb04274b3491fdfe91b2e5acc23dc3f3064a86landley	}
9309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley}
9409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
95efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landleyvoid df_main(void)
96c56215062c961402515daeef8330ed75cd94af29landley{
9709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	struct mtab_list *mt, *mt2, *mtlist;
9809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
9909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// Handle -P and -k
100b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley	TT.units = 1024;
10109ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
10209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley		// Units are 512 bytes if you select "pedantic" without "kilobytes".
103b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley		if ((toys.optflags&3) == 1) TT.units = 512;
10409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley		printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n",
105b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley			TT.units);
10609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	} else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on");
1074f344e356d2c36c4b1df46917eaef25f82ca79a9landley
1084f344e356d2c36c4b1df46917eaef25f82ca79a9landley	mtlist = getmountlist(1);
10909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
11009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	// If we have a list of filesystems on the command line, loop through them.
1118324b89598b2aee0957a0378f0f63ff5755498beRob Landley	if (*toys.optargs) {
1128324b89598b2aee0957a0378f0f63ff5755498beRob Landley		char **next;
11309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
1148324b89598b2aee0957a0378f0f63ff5755498beRob Landley		for(next = toys.optargs; *next; next++) {
11509ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			struct stat st;
11609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
11709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			// Stat it (complain if we can't).
1184541e881568708cc9462f67abecf01ee55e6e611Rob Landley			if(stat(*next, &st)) {
119d0c379e3bdc6d4403dab8f591fd9c09a58a9b89dCharlie Shepherd				perror_msg("`%s'", *next);
12009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley				toys.exitval = 1;
12109ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley				continue;
12209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			}
12309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
12409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			// Find and display this filesystem.  Use _last_ hit in case of
12509ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			// -- bind mounts.
12609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			mt2 = NULL;
12709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			for (mt = mtlist; mt; mt = mt->next)
12809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley				if (st.st_dev == mt->stat.st_dev) mt2 = mt;
12909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			show_mt(mt2);
13009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley		}
13109ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley	} else {
13209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley		// Get and loop through mount list.
13309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
13409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley		for (mt = mtlist; mt; mt = mt->next) {
13509ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			struct mtab_list *mt2, *mt3;
13609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
13709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			if (!mt->stat.st_dev) continue;
13809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley
13909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			// Filter out overmounts.
14009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			mt3 = mt;
14109ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			for (mt2 = mt->next; mt2; mt2 = mt2->next) {
14209ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley				if (mt->stat.st_dev == mt2->stat.st_dev) {
14309ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley					// For --bind mounts, take last match
14409ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley					if (!strcmp(mt->device, mt2->device)) mt3 = mt2;
14509ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley					// Filter out overmounts
14609ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley					mt2->stat.st_dev = 0;
14709ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley				}
14809ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			}
14909ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley			show_mt(mt3);
15009ea7ac1a269db3c9a3b76840b37a7cb1eccbc24landley		}
1514f344e356d2c36c4b1df46917eaef25f82ca79a9landley	}
1524f344e356d2c36c4b1df46917eaef25f82ca79a9landley
153de05a7024f4be6826d05c40aa029fe2bbf6d2818Rob Landley	if (CFG_TOYBOX_FREE) llist_free(mtlist, NULL);
154c56215062c961402515daeef8330ed75cd94af29landley}
155