btrfs-progs: add options to tune units for fi df output
The size unit format is a longstanding annoyance. This patch is based on the work of Nils and Alexandre and enhances the options. It's possible to select raw bytes, SI-based or IEC-based compact units (human frientdly) or a fixed base from kilobytes to terabytes. The default is compact human readable IEC-based, no change to current version. CC: Nils Steinger <nst@voidptr.de> CC: Alexandre Oliva <oliva@gnu.org> Reviewed-by: Hugo Mills <hugo@carfax.org.uk> Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
f404c1ab6c
commit
0b90a24e11
|
@ -17,8 +17,31 @@ resizing, defragment.
|
|||
|
||||
SUBCOMMAND
|
||||
----------
|
||||
*df* <path> [<path>...]::
|
||||
*df* [options] <path>::
|
||||
Show space usage information for a mount point.
|
||||
+
|
||||
`Options`
|
||||
+
|
||||
-b|--raw::::
|
||||
raw numbers in bytes, without the 'B' suffix
|
||||
-h::::
|
||||
print human friendly numbers, base 1024, this is the default
|
||||
-H::::
|
||||
print human friendly numbers, base 1000
|
||||
--iec::::
|
||||
select the 1024 base for the following options, according to the IEC standard
|
||||
--si::::
|
||||
select the 1000 base for the following options, according to the SI standard
|
||||
-k|--kbytes::::
|
||||
show sizes in KiB, or kB with --si
|
||||
-m|--mbytes::::
|
||||
show sizes in MiB, or mB with --si
|
||||
-g|--gbytes::::
|
||||
show sizes in GiB, or gB with --si
|
||||
-t|--tbytes::::
|
||||
show sizes in TiB, or tB with --si
|
||||
|
||||
If conflicting options are passed, the last one takes precedence.
|
||||
|
||||
*show* [--mounted|--all-devices|<path>|<uuid>|<device>|<label>]::
|
||||
Show the btrfs filesystem with some additional info.
|
||||
|
|
|
@ -113,9 +113,18 @@ static const char * const filesystem_cmd_group_usage[] = {
|
|||
};
|
||||
|
||||
static const char * const cmd_df_usage[] = {
|
||||
"btrfs filesystem df <path>",
|
||||
"Show space usage information for a mount point",
|
||||
NULL
|
||||
"btrfs filesystem df [options] <path>",
|
||||
"Show space usage information for a mount point",
|
||||
"-b|--raw raw numbers in bytes",
|
||||
"-h human friendly numbers, base 1024 (default)",
|
||||
"-H human friendly numbers, base 1000",
|
||||
"--iec use 1024 as a base (KiB, MiB, GiB, TiB)",
|
||||
"--si use 1000 as a base (kB, mB, gB, tB)",
|
||||
"-k|--kbytes show sizes in KiB, or kB with --si",
|
||||
"-m|--mbytes show sizes in MiB, or mB with --si",
|
||||
"-g|--gbytes show sizes in GiB, or gB with --si",
|
||||
"-t|--tbytes show sizes in TiB, or tB with --si",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *group_type_str(u64 flag)
|
||||
|
@ -209,7 +218,7 @@ static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void print_df(struct btrfs_ioctl_space_args *sargs)
|
||||
static void print_df(struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
|
||||
{
|
||||
u64 i;
|
||||
struct btrfs_ioctl_space_info *sp = sargs->spaces;
|
||||
|
@ -218,8 +227,8 @@ static void print_df(struct btrfs_ioctl_space_args *sargs)
|
|||
printf("%s, %s: total=%s, used=%s\n",
|
||||
group_type_str(sp->flags),
|
||||
group_profile_str(sp->flags),
|
||||
pretty_size(sp->total_bytes),
|
||||
pretty_size(sp->used_bytes));
|
||||
pretty_size_mode(sp->total_bytes, unit_mode),
|
||||
pretty_size_mode(sp->used_bytes, unit_mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,12 +238,62 @@ static int cmd_df(int argc, char **argv)
|
|||
int ret;
|
||||
int fd;
|
||||
char *path;
|
||||
DIR *dirstream = NULL;
|
||||
DIR *dirstream = NULL;
|
||||
unsigned unit_mode = UNITS_DEFAULT;
|
||||
|
||||
if (check_argc_exact(argc, 2))
|
||||
optind = 1;
|
||||
while (1) {
|
||||
int long_index;
|
||||
static const struct option long_options[] = {
|
||||
{ "raw", no_argument, NULL, 'b'},
|
||||
{ "kbytes", no_argument, NULL, 'k'},
|
||||
{ "mbytes", no_argument, NULL, 'm'},
|
||||
{ "gbytes", no_argument, NULL, 'g'},
|
||||
{ "tbytes", no_argument, NULL, 't'},
|
||||
{ "si", no_argument, NULL, 256},
|
||||
{ "iec", no_argument, NULL, 257},
|
||||
};
|
||||
int c = getopt_long(argc, argv, "bhHkmgt", long_options,
|
||||
&long_index);
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'b':
|
||||
unit_mode = UNITS_RAW;
|
||||
break;
|
||||
case 'k':
|
||||
units_set_base(&unit_mode, UNITS_KBYTES);
|
||||
break;
|
||||
case 'm':
|
||||
units_set_base(&unit_mode, UNITS_MBYTES);
|
||||
break;
|
||||
case 'g':
|
||||
units_set_base(&unit_mode, UNITS_GBYTES);
|
||||
break;
|
||||
case 't':
|
||||
units_set_base(&unit_mode, UNITS_TBYTES);
|
||||
break;
|
||||
case 'h':
|
||||
unit_mode = UNITS_HUMAN_BINARY;
|
||||
break;
|
||||
case 'H':
|
||||
unit_mode = UNITS_HUMAN_DECIMAL;
|
||||
break;
|
||||
case 256:
|
||||
units_set_mode(&unit_mode, UNITS_DECIMAL);
|
||||
break;
|
||||
case 257:
|
||||
units_set_mode(&unit_mode, UNITS_BINARY);
|
||||
break;
|
||||
default:
|
||||
usage(cmd_df_usage);
|
||||
}
|
||||
}
|
||||
|
||||
if (check_argc_max(argc, optind + 1))
|
||||
usage(cmd_df_usage);
|
||||
|
||||
path = argv[1];
|
||||
path = argv[optind];
|
||||
|
||||
fd = open_file_or_dir(path, &dirstream);
|
||||
if (fd < 0) {
|
||||
|
@ -244,7 +303,7 @@ static int cmd_df(int argc, char **argv)
|
|||
ret = get_df(fd, &sargs);
|
||||
|
||||
if (ret == 0) {
|
||||
print_df(sargs);
|
||||
print_df(sargs, unit_mode);
|
||||
free(sargs);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: get_df failed %s\n", strerror(-ret));
|
||||
|
|
52
utils.c
52
utils.c
|
@ -1297,35 +1297,38 @@ out:
|
|||
static const char* unit_suffix_binary[] =
|
||||
{ "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
|
||||
static const char* unit_suffix_decimal[] =
|
||||
{ "B", "KB", "MB", "GB", "TB", "PB", "EB"};
|
||||
{ "B", "kB", "mB", "gB", "tB", "pB", "eB"};
|
||||
|
||||
int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
|
||||
int pretty_size_snprintf(u64 size, char *str, size_t str_size, unsigned unit_mode)
|
||||
{
|
||||
int num_divs;
|
||||
float fraction;
|
||||
int base = 0;
|
||||
u64 base = 0;
|
||||
int mult = 0;
|
||||
const char** suffix = NULL;
|
||||
u64 last_size;
|
||||
|
||||
if (str_size == 0)
|
||||
return 0;
|
||||
|
||||
if (unit_mode == UNITS_RAW) {
|
||||
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_RAW) {
|
||||
snprintf(str, str_size, "%llu", size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unit_mode == UNITS_BINARY) {
|
||||
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_BINARY) {
|
||||
base = 1024;
|
||||
mult = 1024;
|
||||
suffix = unit_suffix_binary;
|
||||
} else if (unit_mode == UNITS_DECIMAL) {
|
||||
} else if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_DECIMAL) {
|
||||
base = 1000;
|
||||
mult = 1000;
|
||||
suffix = unit_suffix_decimal;
|
||||
}
|
||||
|
||||
/* Unknown mode */
|
||||
if (!base) {
|
||||
fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d",
|
||||
fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d\n",
|
||||
unit_mode);
|
||||
assert(0);
|
||||
return -1;
|
||||
|
@ -1333,11 +1336,22 @@ int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
|
|||
|
||||
num_divs = 0;
|
||||
last_size = size;
|
||||
|
||||
while (size >= base) {
|
||||
last_size = size;
|
||||
size /= base;
|
||||
num_divs++;
|
||||
switch (unit_mode & UNITS_MODE_MASK) {
|
||||
case UNITS_TBYTES: base *= mult; num_divs++;
|
||||
case UNITS_GBYTES: base *= mult; num_divs++;
|
||||
case UNITS_MBYTES: base *= mult; num_divs++;
|
||||
case UNITS_KBYTES: num_divs++;
|
||||
break;
|
||||
case UNITS_BYTES:
|
||||
base = 1;
|
||||
num_divs = 0;
|
||||
break;
|
||||
default:
|
||||
while (size >= mult) {
|
||||
last_size = size;
|
||||
size /= mult;
|
||||
num_divs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_divs >= ARRAY_SIZE(unit_suffix_binary)) {
|
||||
|
@ -2377,3 +2391,17 @@ int test_isdir(const char *path)
|
|||
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
void units_set_mode(unsigned *units, unsigned mode)
|
||||
{
|
||||
unsigned base = *units & UNITS_MODE_MASK;
|
||||
|
||||
*units = base | mode;
|
||||
}
|
||||
|
||||
void units_set_base(unsigned *units, unsigned base)
|
||||
{
|
||||
unsigned mode = *units & ~UNITS_MODE_MASK;
|
||||
|
||||
*units = base | mode;
|
||||
}
|
||||
|
|
30
utils.h
30
utils.h
|
@ -48,12 +48,26 @@ void fixup_argv0(char **argv, const char *token);
|
|||
void set_argv0(char **argv);
|
||||
|
||||
/*
|
||||
* Output mode of byte units
|
||||
* Output modes of size
|
||||
*/
|
||||
#define UNITS_RAW (1)
|
||||
#define UNITS_BINARY (2)
|
||||
#define UNITS_DECIMAL (3)
|
||||
#define UNITS_HUMAN UNITS_BINARY
|
||||
#define UNITS_RESERVED (0)
|
||||
#define UNITS_BYTES (1)
|
||||
#define UNITS_KBYTES (2)
|
||||
#define UNITS_MBYTES (3)
|
||||
#define UNITS_GBYTES (4)
|
||||
#define UNITS_TBYTES (5)
|
||||
#define UNITS_RAW (1U << UNITS_MODE_SHIFT)
|
||||
#define UNITS_BINARY (2U << UNITS_MODE_SHIFT)
|
||||
#define UNITS_DECIMAL (3U << UNITS_MODE_SHIFT)
|
||||
#define UNITS_MODE_MASK ((1U << UNITS_MODE_SHIFT) - 1)
|
||||
#define UNITS_MODE_SHIFT (8)
|
||||
#define UNITS_HUMAN_BINARY (UNITS_BINARY)
|
||||
#define UNITS_HUMAN_DECIMAL (UNITS_DECIMAL)
|
||||
#define UNITS_HUMAN (UNITS_HUMAN_BINARY)
|
||||
#define UNITS_DEFAULT (UNITS_HUMAN)
|
||||
|
||||
void units_set_mode(unsigned *units, unsigned mode);
|
||||
void units_set_base(unsigned *units, unsigned base);
|
||||
|
||||
int make_btrfs(int fd, const char *device, const char *label,
|
||||
char *fs_uuid, u64 blocks[6], u64 num_bytes, u32 nodesize,
|
||||
|
@ -76,12 +90,12 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
|
|||
int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
|
||||
int super_offset);
|
||||
|
||||
int pretty_size_snprintf(u64 size, char *str, size_t str_bytes, int unit_mode);
|
||||
#define pretty_size(size) pretty_size_mode(size, UNITS_BINARY)
|
||||
int pretty_size_snprintf(u64 size, char *str, size_t str_bytes, unsigned unit_mode);
|
||||
#define pretty_size(size) pretty_size_mode(size, UNITS_DEFAULT)
|
||||
#define pretty_size_mode(size, mode) \
|
||||
({ \
|
||||
static __thread char _str[32]; \
|
||||
(void)pretty_size_snprintf((size), _str, sizeof(_str), mode); \
|
||||
(void)pretty_size_snprintf((size), _str, sizeof(_str), (mode)); \
|
||||
_str; \
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue