df.c revision b1aaba1fc8176ac0b7c202a664d2554aa0967116
1/* vi: set sw=4 ts=4: 2 * 3 * df.c - report free disk space. 4 * 5 * Copyright 2006 Rob Landley <rob@landley.net> 6 * 7 * See http://www.opengroup.org/onlinepubs/009695399/utilities/df.html 8 9USE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN)) 10 11config DF 12 bool "df (disk free)" 13 default y 14 help 15 usage: df [-t type] [FILESYSTEM ...] 16 17 The "disk free" command, df shows total/used/available disk space for 18 each filesystem listed on the command line, or all currently mounted 19 filesystems. 20 21 -t type 22 Display only filesystems of this type. 23 24config DF_PEDANTIC 25 bool "options -P and -k" 26 default y 27 depends on DF 28 help 29 usage: df [-Pk] 30 31 -P The SUSv3 "Pedantic" option 32 33 Provides a slightly less useful output format dictated by 34 the Single Unix Specification version 3, and sets the 35 units to 512 bytes instead of the default 1024 bytes. 36 37 -k Sets units back to 1024 bytes (the default without -P) 38*/ 39 40#include "toys.h" 41 42DEFINE_GLOBALS( 43 struct arg_list *fstype; 44 45 long units; 46) 47 48#define TT this.df 49 50static void show_mt(struct mtab_list *mt) 51{ 52 int len; 53 long size, used, avail, percent; 54 uint64_t block; 55 56 // Return if it wasn't found (should never happen, but with /etc/mtab...) 57 if (!mt) return; 58 59 // If we have -t, skip other filesystem types 60 if (TT.fstype) { 61 struct arg_list *al; 62 63 for (al = TT.fstype; al; al = al->next) { 64 if (!strcmp(mt->type, al->arg)) break; 65 } 66 if (!al) return; 67 } 68 69 // If we don't have -a, skip synthetic filesystems 70 if (!(toys.optflags & 1) && !mt->statvfs.f_blocks) return; 71 72 // Figure out how much total/used/free space this filesystem has, 73 // forcing 64-bit math because filesystems are big now. 74 block = mt->statvfs.f_bsize ? : 1; 75 size = (long)((block * mt->statvfs.f_blocks) / TT.units); 76 used = (long)((block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree)) 77 / TT.units); 78 avail = (long)((block 79 * (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree)) 80 / TT.units); 81 percent = size ? 100-(long)((100*(uint64_t)avail)/size) : 0; 82 83 // Figure out appropriate spacing 84 len = 25 - strlen(mt->device); 85 if (len < 1) len = 1; 86 if (CFG_DF_PEDANTIC && (toys.optflags & 8)) { 87 printf("%s %ld %ld %ld %ld%% %s\n", mt->device, size, used, avail, 88 percent, mt->dir); 89 } else { 90 printf("%s% *ld % 10ld % 9ld % 3ld%% %s\n",mt->device, len, 91 size, used, avail, percent, mt->dir); 92 } 93} 94 95void df_main(void) 96{ 97 struct mtab_list *mt, *mt2, *mtlist; 98 99 // Handle -P and -k 100 TT.units = 1024; 101 if (CFG_DF_PEDANTIC && (toys.optflags & 8)) { 102 // Units are 512 bytes if you select "pedantic" without "kilobytes". 103 if ((toys.optflags&3) == 1) TT.units = 512; 104 printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n", 105 TT.units); 106 } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); 107 108 mtlist = getmountlist(1); 109 110 // If we have a list of filesystems on the command line, loop through them. 111 if (*toys.optargs) { 112 char **next; 113 114 for(next = toys.optargs; *next; next++) { 115 struct stat st; 116 117 // Stat it (complain if we can't). 118 if(stat(*next, &st)) { 119 perror_msg("`%s'", *next); 120 toys.exitval = 1; 121 continue; 122 } 123 124 // Find and display this filesystem. Use _last_ hit in case of 125 // -- bind mounts. 126 mt2 = NULL; 127 for (mt = mtlist; mt; mt = mt->next) 128 if (st.st_dev == mt->stat.st_dev) mt2 = mt; 129 show_mt(mt2); 130 } 131 } else { 132 // Get and loop through mount list. 133 134 for (mt = mtlist; mt; mt = mt->next) { 135 struct mtab_list *mt2, *mt3; 136 137 if (!mt->stat.st_dev) continue; 138 139 // Filter out overmounts. 140 mt3 = mt; 141 for (mt2 = mt->next; mt2; mt2 = mt2->next) { 142 if (mt->stat.st_dev == mt2->stat.st_dev) { 143 // For --bind mounts, take last match 144 if (!strcmp(mt->device, mt2->device)) mt3 = mt2; 145 // Filter out overmounts 146 mt2->stat.st_dev = 0; 147 } 148 } 149 show_mt(mt3); 150 } 151 } 152 153 if (CFG_TOYBOX_FREE) llist_free(mtlist, NULL); 154} 155