df: Rework formatting, implement POSIX required flags
POSIX flags: - -P for a fixed format usable in scripts with only some fields - -k for kilobytes (the default for -P is 512 byte blocks). Rename -b to -k accordingly and implement a new -b to force 512 byte blocks Default format rework: - Add usage percentage - To keep things under 80 columns, use two lines per device: the first shows the mountpoint and the second shows the details. - Mount point is shown in bold and other fields are indented Change-Id: I33843caf67ff01509ce38bf0b5fdd18517ea1aa9 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9276 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
b34fdb5655
commit
a9eae2a658
+134
-26
@@ -19,6 +19,15 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
enum FormatType
|
||||
{
|
||||
k512Block,
|
||||
k1024Block,
|
||||
kHumanReadable,
|
||||
kUnspecified
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
PrintFlag(uint32 deviceFlags, uint32 testFlag, char yes, char no)
|
||||
{
|
||||
@@ -58,7 +67,7 @@ PrintType(const char *fileSystem)
|
||||
char type[16];
|
||||
strlcpy(type, fileSystem, sizeof(type));
|
||||
|
||||
printf("%-9s", type);
|
||||
printf("%11s ", type);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,13 +96,49 @@ ByteString(int64 numBlocks, int64 blockSize)
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
UsePercentage(int64 totalBlocks, int64 freeBlocks, bool compact = false)
|
||||
{
|
||||
float usage;
|
||||
static char string[8];
|
||||
|
||||
if (totalBlocks == 0 && freeBlocks == 0)
|
||||
usage = 100;
|
||||
else if (totalBlocks == 0)
|
||||
usage = 0;
|
||||
else
|
||||
usage = 100 - 100 * (1. * freeBlocks / totalBlocks);
|
||||
|
||||
if (compact) {
|
||||
if (usage < 10)
|
||||
sprintf(string, " %.0f%%", round(usage));
|
||||
else if (usage < 100)
|
||||
sprintf(string, " %.0f%%", round(usage));
|
||||
else
|
||||
sprintf(string, "%.0f%%", round(usage));
|
||||
}
|
||||
else {
|
||||
if (usage < 10)
|
||||
sprintf(string, " %.1f %%", usage);
|
||||
else if (usage < 100)
|
||||
sprintf(string, " %.1f %%", usage);
|
||||
else
|
||||
sprintf(string, "%.1f %%", usage);
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PrintBlocks(int64 blocks, int64 blockSize, bool showBlocks)
|
||||
PrintBlocks(int64 blocks, int64 blockSize, FormatType format)
|
||||
{
|
||||
char temp[1024];
|
||||
|
||||
if (showBlocks)
|
||||
if (format == k1024Block)
|
||||
sprintf(temp, "%" B_PRId64, blocks * (blockSize / 1024));
|
||||
else if (format == k512Block)
|
||||
sprintf(temp, "%" B_PRId64, blocks * (blockSize / 512));
|
||||
else
|
||||
strcpy(temp, ByteString(blocks, blockSize));
|
||||
|
||||
@@ -110,6 +155,12 @@ PrintVerbose(dev_t device)
|
||||
return;
|
||||
}
|
||||
|
||||
int64 usedBlocks = info.total_blocks - info.free_blocks;
|
||||
// Used blocks can't be negative, but ramfs reports available RAM as free_blocks,
|
||||
// and always 0 for total_blocks, so we need to check for that.
|
||||
if (usedBlocks < 0)
|
||||
usedBlocks = 0;
|
||||
|
||||
printf(" Device No.: %" B_PRIdDEV "\n", info.dev);
|
||||
PrintMountPoint(info.dev, true);
|
||||
printf(" Volume Name: \"%s\"\n", info.volume_name);
|
||||
@@ -131,16 +182,20 @@ PrintVerbose(dev_t device)
|
||||
ByteString(info.block_size, 1), info.block_size);
|
||||
printf(" Total Blocks: %10s (%" B_PRIdOFF " blocks)\n",
|
||||
ByteString(info.total_blocks, info.block_size), info.total_blocks);
|
||||
printf(" Used Blocks: %10s (%" B_PRIdOFF " blocks)\n",
|
||||
ByteString(usedBlocks, info.block_size), usedBlocks);
|
||||
printf(" Free Blocks: %10s (%" B_PRIdOFF " blocks)\n",
|
||||
ByteString(info.free_blocks, info.block_size), info.free_blocks);
|
||||
printf(" Usage %%: %s\n", UsePercentage(info.total_blocks, info.free_blocks));
|
||||
printf(" Total Nodes: %" B_PRIdOFF "\n", info.total_nodes);
|
||||
printf(" Used Nodes: %" B_PRIdOFF "\n", info.total_nodes - info.free_nodes);
|
||||
printf(" Free Nodes: %" B_PRIdOFF "\n", info.free_nodes);
|
||||
printf(" Root Inode: %" B_PRIdINO "\n", info.root);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PrintCompact(dev_t device, bool showBlocks, bool all)
|
||||
PrintCompact(dev_t device, FormatType format, bool strictPosix, bool all)
|
||||
{
|
||||
fs_info info;
|
||||
if (fs_stat_dev(device, &info) != B_OK)
|
||||
@@ -149,21 +204,39 @@ PrintCompact(dev_t device, bool showBlocks, bool all)
|
||||
if (!all && (info.flags & B_FS_IS_PERSISTENT) == 0)
|
||||
return;
|
||||
|
||||
PrintType(info.fsh_name);
|
||||
PrintBlocks(info.total_blocks, info.block_size, showBlocks);
|
||||
PrintBlocks(info.free_blocks, info.block_size, showBlocks);
|
||||
int64 usedBlocks = info.total_blocks - info.free_blocks;
|
||||
// Used blocks can't be negative, but ramfs reports available RAM as free_blocks,
|
||||
// and always 0 for total_blocks, so we need to check for that.
|
||||
if (usedBlocks < 0)
|
||||
usedBlocks = 0;
|
||||
|
||||
printf(" ");
|
||||
PrintFlag(info.flags, B_FS_HAS_QUERY, 'Q', '-');
|
||||
PrintFlag(info.flags, B_FS_HAS_ATTR, 'A', '-');
|
||||
PrintFlag(info.flags, B_FS_HAS_MIME, 'M', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_SHARED, 'S', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_PERSISTENT, 'P', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_REMOVABLE, 'R', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_READONLY, '-', 'W');
|
||||
if (strictPosix) {
|
||||
printf("%24s ", info.device_name);
|
||||
PrintBlocks(info.total_blocks, info.block_size, format);
|
||||
PrintBlocks(usedBlocks, info.block_size, format);
|
||||
PrintBlocks(info.free_blocks, info.block_size, format);
|
||||
printf(" %s ", UsePercentage(info.total_blocks, info.free_blocks, true));
|
||||
PrintMountPoint(info.dev, false);
|
||||
} else {
|
||||
printf("\x1B[1m");
|
||||
PrintMountPoint(info.dev, false);
|
||||
printf("\x1B[0m\n");
|
||||
PrintType(info.fsh_name);
|
||||
PrintBlocks(info.total_blocks, info.block_size, format);
|
||||
PrintBlocks(usedBlocks, info.block_size, format);
|
||||
|
||||
printf(" %24s ", info.device_name);
|
||||
PrintMountPoint(info.dev, false);
|
||||
printf(" ");
|
||||
PrintFlag(info.flags, B_FS_HAS_QUERY, 'Q', '-');
|
||||
PrintFlag(info.flags, B_FS_HAS_ATTR, 'A', '-');
|
||||
PrintFlag(info.flags, B_FS_HAS_MIME, 'M', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_SHARED, 'S', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_PERSISTENT, 'P', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_REMOVABLE, 'R', '-');
|
||||
PrintFlag(info.flags, B_FS_IS_READONLY, '-', 'W');
|
||||
|
||||
printf(" %6s ", UsePercentage(info.total_blocks, info.free_blocks, true));
|
||||
printf("%-24s", info.device_name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -171,10 +244,13 @@ PrintCompact(dev_t device, bool showBlocks, bool all)
|
||||
void
|
||||
ShowUsage(const char *programName)
|
||||
{
|
||||
printf("usage: %s [--help | --blocks, -b | -all, -a] [<path-to-device>]\n"
|
||||
printf("usage: %s [--help | --blocks, -b | -all, -a] [<path-to-volume>]\n"
|
||||
" -a, --all\tinclude all file systems, also those not visible from Tracker\n"
|
||||
" -b, --blocks\tshow device size in blocks of 1024 bytes\n"
|
||||
"If <path-to-device> is used, detailed info for that device only will be listed.\n"
|
||||
" -b, --blocks\tshow device size in blocks of 512 bytes\n"
|
||||
" -h, --human\tshow device size in blocks of 1024 bytes\n"
|
||||
" -k, --kilobytes\tshow device size in blocks of 1024 bytes\n"
|
||||
" -P, --posix\tproduce output in the format specified by POSIX\n"
|
||||
"If <path-to-volume> is used, detailed info for that volume only will be listed.\n"
|
||||
"Flags:\n"
|
||||
" Q: has query\n"
|
||||
" A: has attribute\n"
|
||||
@@ -194,7 +270,8 @@ main(int argc, char **argv)
|
||||
if (strrchr(programName, '/'))
|
||||
programName = strrchr(programName, '/') + 1;
|
||||
|
||||
bool showBlocks = false;
|
||||
FormatType format = kUnspecified;
|
||||
bool strictPosix = false;
|
||||
bool all = false;
|
||||
dev_t device = -1;
|
||||
|
||||
@@ -207,10 +284,17 @@ main(int argc, char **argv)
|
||||
all = true;
|
||||
break;
|
||||
case 'b':
|
||||
showBlocks = true;
|
||||
format = k512Block;
|
||||
break;
|
||||
case 'h':
|
||||
// human readable units in Unix df
|
||||
format = kHumanReadable;
|
||||
break;
|
||||
case 'k':
|
||||
format = k1024Block;
|
||||
break;
|
||||
case 'P':
|
||||
strictPosix = true;
|
||||
break;
|
||||
default:
|
||||
ShowUsage(programName);
|
||||
@@ -221,7 +305,13 @@ main(int argc, char **argv)
|
||||
if (!strcmp(arg, "all"))
|
||||
all = true;
|
||||
else if (!strcmp(arg, "blocks"))
|
||||
showBlocks = true;
|
||||
format = k512Block;
|
||||
else if (!strcmp(arg, "human"))
|
||||
format = kHumanReadable;
|
||||
else if (!strcmp(arg, "kilobytes"))
|
||||
format = k1024Block;
|
||||
else if (!strcmp(arg, "posix"))
|
||||
strictPosix = true;
|
||||
else
|
||||
ShowUsage(programName);
|
||||
}
|
||||
@@ -229,6 +319,17 @@ main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine default format if nothing was specified
|
||||
// This is done after option parsing so that -k -P gives kilobytes as expected
|
||||
// Otherwise -P could force 512-block format, but it would overwrite the effect of other
|
||||
// options.
|
||||
if (format == kUnspecified) {
|
||||
if (strictPosix)
|
||||
format = k512Block;
|
||||
else
|
||||
format = kHumanReadable;
|
||||
}
|
||||
|
||||
// Do we already have a device? Then let's print out detailed info about that
|
||||
|
||||
if (argv[0] != NULL) {
|
||||
@@ -238,12 +339,19 @@ main(int argc, char **argv)
|
||||
|
||||
// If not, then just iterate over all devices and give a compact summary
|
||||
|
||||
printf(" Type Total Free Flags Device Mounted on\n"
|
||||
"--------- --------- --------- ------- ------------------------ -----------------\n");
|
||||
if (strictPosix) {
|
||||
printf(" Filesystem %11s Used Available Capacity Mounted on\n",
|
||||
format == kHumanReadable ? "Capacity"
|
||||
: (format == k512Block ? "512-blocks" : "1024-blocks"));
|
||||
} else {
|
||||
printf("\x1B[1mVolume\x1B[0m\n"
|
||||
" Type Total Free Flags Used%% Device\n"
|
||||
"----------- ---------- --------- ------- ------ -------------------\n");
|
||||
}
|
||||
|
||||
int32 cookie = 0;
|
||||
while ((device = next_dev(&cookie)) >= B_OK) {
|
||||
PrintCompact(device, showBlocks, all);
|
||||
PrintCompact(device, format, strictPosix, all);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user