The automatic unit selection makes parsing the output of `filesystem df` 
unnecessarily difficult.
Using the new options -b, -k, -m, and -g, the output unit can be set to bytes, 
kibi-, mebi-, and gibibytes respectively.

Signed-off-by: Nils Steinger <n...@voidptr.de>
---
 cmds-filesystem.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 utils.c           | 30 +++++++++++++++++++++++++++
 utils.h           |  8 +++++++
 3 files changed, 93 insertions(+), 7 deletions(-)

diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index 306f715..54406a5 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -113,8 +113,13 @@ static const char * const filesystem_cmd_group_usage[] = {
 };
 
 static const char * const cmd_df_usage[] = {
-       "btrfs filesystem df <path>",
+       "btrfs filesystem df [options] <path>",
        "Show space usage information for a mount point",
+       "",
+       "-b             display all values in bytes",
+       "-k             display all values in kibibytes",
+       "-m             display all values in mebibytes",
+       "-g             display all values in gibibytes",
        NULL
 };
 
@@ -204,7 +209,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, int output_unit)
 {
        u64 i;
        struct btrfs_ioctl_space_info *sp = sargs->spaces;
@@ -213,8 +218,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));
+                       fixed_unit_size(sp->total_bytes, output_unit),
+                       fixed_unit_size(sp->used_bytes, output_unit));
        }
 }
 
@@ -223,13 +228,56 @@ static int cmd_df(int argc, char **argv)
        struct btrfs_ioctl_space_args *sargs = NULL;
        int ret;
        int fd;
+       int output_unit = 0;
+       int multiple_options_specified = 0;
        char *path;
        DIR  *dirstream = NULL;
 
-       if (check_argc_exact(argc, 2))
+       optind = 1;
+       while(1) {
+               int c = getopt(argc, argv, "bkmg");
+               if (c < 0)
+                       break;
+
+               switch(c) {
+               case 'b':
+                       if (output_unit > 0)
+                               multiple_options_specified = 1;
+
+                       output_unit = 1;
+                       break;
+               case 'k':
+                       if (output_unit > 0)
+                               multiple_options_specified = 1;
+
+                       output_unit = 1024;
+                       break;
+               case 'm':
+                       if (output_unit > 0)
+                               multiple_options_specified = 1;
+
+                       output_unit = 1024 * 1024;
+                       break;
+               case 'g':
+                       if (output_unit > 0)
+                               multiple_options_specified = 1;
+
+                       output_unit = 1024 * 1024 * 1024;
+                       break;
+               default:
+                       usage(cmd_df_usage);
+               }
+       }
+
+       if (multiple_options_specified) {
+               fprintf(stderr, "Please only specify one the unit selection 
parameters -b/k/m/g\n.");
+               return EINVAL;
+       }
+
+       if (check_argc_exact(argc - optind, 1))
                usage(cmd_df_usage);
 
-       path = argv[1];
+       path = argv[argc - 1];
 
        fd = open_file_or_dir(path, &dirstream);
        if (fd < 0) {
@@ -239,7 +287,7 @@ static int cmd_df(int argc, char **argv)
        ret = get_df(fd, &sargs);
 
        if (!ret && sargs) {
-               print_df(sargs);
+               print_df(sargs, output_unit);
                free(sargs);
        } else {
                fprintf(stderr, "ERROR: get_df failed %s\n", strerror(-ret));
diff --git a/utils.c b/utils.c
index e130849..971e0ac 100644
--- a/utils.c
+++ b/utils.c
@@ -1280,6 +1280,36 @@ int pretty_size_snprintf(u64 size, char *str, size_t 
str_bytes)
        return snprintf(str, str_bytes, "%.2f%s", fraction,
                        size_strs[num_divs]);
 }
+int fixed_unit_size_snprintf(u64 size, int unit, char *str, size_t str_bytes)
+{
+       int size_str_idx;
+       float fraction;
+
+       switch (unit) {
+       case 1:
+               size_str_idx = 0;
+               break;
+       case 1024:
+               size_str_idx = 1;
+               break;
+       case 1024 * 1024:
+               size_str_idx = 2;
+               break;
+       case 1024 * 1024 * 1024:
+               size_str_idx = 3;
+               break;
+       default:
+               return pretty_size_snprintf(size, str, str_bytes);
+       }
+
+       if (str_bytes == 0)
+               return 0;
+
+       fraction = (float)size / unit;
+
+       return snprintf(str, str_bytes, "%.2f%s", fraction,
+                       size_strs[size_str_idx]);
+}
 
 /*
  * __strncpy__null - strncpy with null termination
diff --git a/utils.h b/utils.h
index db8d63c..313408b 100644
--- a/utils.h
+++ b/utils.h
@@ -67,6 +67,14 @@ int pretty_size_snprintf(u64 size, char *str, size_t 
str_bytes);
                _str;                                                   \
        })
 
+int fixed_unit_size_snprintf(u64 size, int unit, char *str, size_t str_bytes);
+#define fixed_unit_size(size, unit)                                            
\
+       ({                                                              \
+               static __thread char _str[24];                          \
+               (void)fixed_unit_size_snprintf((size), (unit), _str, 
sizeof(_str));     \
+               _str;                                                   \
+       })
+
 int get_mountpt(char *dev, char *mntpt, size_t size);
 int btrfs_scan_block_devices(int run_ioctl);
 u64 parse_size(char *s);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to