From: Audrius Butkevicius <audrius.butkevicius@elastichosts.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH] btrfs-progs: add options for changing size representations
Date: Mon, 11 Mar 2013 10:12:44 +0000 [thread overview]
Message-ID: <20130311101242.GA18346@gmail.com> (raw)
Add '--si', '-h'/'--human-readable' and '--block-size' global options,
which allow users to customize the way sizes are displayed.
Options and their format tries to mimic GNU ls utility.
Signed-off-by: Audrius Butkevicius <audrius.butkevicius@elastichosts.com>
---
btrfs.c | 3 ++
utils.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
utils.h | 6 +++
3 files changed, 138 insertions(+), 17 deletions(-)
diff --git a/btrfs.c b/btrfs.c
index 691adef..6a8fc30 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -22,6 +22,8 @@
#include "crc32c.h"
#include "commands.h"
#include "version.h"
+#include "ctree.h"
+#include "utils.h"
static const char * const btrfs_cmd_group_usage[] = {
"btrfs [--help] [--version] <group> [<group>...] <command> [<args>]",
@@ -291,6 +293,7 @@ int main(int argc, char **argv)
crc32c_optimization_init();
+ handle_size_unit_args(&argc, &argv);
fixup_argv0(argv, cmd->token);
exit(cmd->fn(argc, argv));
}
diff --git a/utils.c b/utils.c
index d660507..58c1919 100644
--- a/utils.c
+++ b/utils.c
@@ -16,6 +16,7 @@
* Boston, MA 021110-1307, USA.
*/
+#define _GNU_SOURCE
#define _XOPEN_SOURCE 700
#define __USE_XOPEN2K8
#define __XOPEN2K8 /* due to an error in dirent.h, to get dirfd() */
@@ -1095,33 +1096,144 @@ out:
return ret;
}
-static char *size_strs[] = { "", "KB", "MB", "GB", "TB",
- "PB", "EB", "ZB", "YB"};
+static int sizes_format = SIZES_FORMAT_BYTES;
+static u64 sizes_divisor = 1;
+
+void remove_arg(int i, int *argc, char ***argv)
+{
+ while (i++ < *argc)
+ (*argv)[i - 1] = (*argv)[i];
+ (*argc)--;
+}
+
+void handle_size_unit_args(int *argc, char ***argv)
+{
+ int k;
+ int base = 1024;
+ char *suffix;
+ char *block_size;
+ u64 value;
+
+ for (k = *argc - 1; k >= 0; k--) {
+ if (!strcmp((*argv)[k], "-h") ||
+ !strcmp((*argv)[k], "--human-readable")) {
+ sizes_format = SIZES_FORMAT_HUMAN;
+ remove_arg(k, argc, argv);
+ } else if (!strcmp((*argv)[k], "--si")) {
+ sizes_format = SIZES_FORMAT_SI;
+ remove_arg(k, argc, argv);
+ } else if (!strncmp((*argv)[k], "--block-size", 12)) {
+ if (strlen((*argv)[k]) < 14 || (*argv)[k][12] != '=') {
+ fprintf(stderr,
+ "--block-size requires an argument\n");
+ exit(1);
+ }
+
+ sizes_format = SIZES_FORMAT_BLOCK;
+ block_size = strchr((*argv)[k], '=');
+
+ errno = 0;
+ value = strtoull(++block_size, &suffix, 10);
+ if (errno == ERANGE && value == ULLONG_MAX) {
+ fprintf(stderr,
+ "--block-size argument '%s' too large\n",
+ block_size);
+ exit(1);
+ }
+ if (suffix == block_size)
+ value = 1;
+
+ if (strlen(suffix) == 1 && value > 0) {
+ base = 1024;
+ } else if (strlen(suffix) == 2 && suffix[1] == 'B'
+ && value > 0) {
+ base = 1000;
+ /* Allow non-zero values without a suffix */
+ } else if (strlen(suffix) != 0 || value == 0) {
+ fprintf(stderr,
+ "invalid --block-size argument '%s'\n",
+ block_size);
+ exit(1);
+ }
+
+ if (strlen(suffix) > 0) {
+ switch(suffix[0]) {
+ case 'E':
+ sizes_divisor *= base;
+ case 'P':
+ sizes_divisor *= base;
+ case 'T':
+ sizes_divisor *= base;
+ case 'G':
+ sizes_divisor *= base;
+ case 'M':
+ sizes_divisor *= base;
+ case 'K':
+ sizes_divisor *= base;
+ break;
+ default:
+ fprintf(stderr,
+ "invalid --block-size \
+argument '%s'\n",
+ block_size);
+ exit(1);
+ }
+ }
+
+ if (ULLONG_MAX / sizes_divisor < value) {
+ fprintf(stderr,
+ "--block-size argument '%s' too large\n",
+ block_size);
+ exit(1);
+ }
+
+ if (suffix != block_size)
+ sizes_divisor *= value;
+
+ remove_arg(k, argc, argv);
+ }
+ }
+}
+
+static char *size_strs[] = { "", "K", "M", "G", "T", "P", "E"};
char *pretty_sizes(u64 size)
{
int num_divs = 0;
- int pretty_len = 16;
+ int sizes_base = 1024;
float fraction;
char *pretty;
-
- if( size < 1024 ){
- fraction = size;
- num_divs = 0;
+ char *sizes_suffix = "iB";
+ u64 last_size;
+
+ if (sizes_format == SIZES_FORMAT_BYTES) {
+ asprintf(&pretty, "%llu", (unsigned long long)size);
+ } else if (sizes_format == SIZES_FORMAT_BLOCK) {
+ fraction = (float)size / sizes_divisor;
+ asprintf(&pretty, "%.2f", fraction);
} else {
- u64 last_size = size;
- num_divs = 0;
- while(size >= 1024){
+ if (sizes_format == SIZES_FORMAT_SI) {
+ sizes_base = 1000;
+ sizes_suffix = "B";
+ }
+
+ if (size < sizes_base) {
+ fraction = size;
+ } else {
last_size = size;
- size /= 1024;
- num_divs ++;
+ while (size >= sizes_base) {
+ last_size = size;
+ size /= 1024;
+ num_divs++;
+ }
+
+ if (num_divs > ARRAY_SIZE(size_strs))
+ return NULL;
+ fraction = (float)last_size / sizes_base;
}
- if (num_divs >= ARRAY_SIZE(size_strs))
- return NULL;
- fraction = (float)last_size / 1024;
+ asprintf(&pretty, "%.2f%s%s", fraction, size_strs[num_divs],
+ sizes_suffix);
}
- pretty = malloc(pretty_len);
- snprintf(pretty, pretty_len, "%.2f%s", fraction, size_strs[num_divs]);
return pretty;
}
diff --git a/utils.h b/utils.h
index 60a0fea..56d7950 100644
--- a/utils.h
+++ b/utils.h
@@ -23,6 +23,11 @@
#define BTRFS_MKFS_SYSTEM_GROUP_SIZE (4 * 1024 * 1024)
+#define SIZES_FORMAT_BYTES 0
+#define SIZES_FORMAT_HUMAN 1
+#define SIZES_FORMAT_SI 2
+#define SIZES_FORMAT_BLOCK 3
+
int make_btrfs(int fd, const char *device, const char *label,
u64 blocks[6], u64 num_bytes, u32 nodesize,
u32 leafsize, u32 sectorsize, u32 stripesize);
@@ -44,6 +49,7 @@ 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);
char *pretty_sizes(u64 size);
+void handle_size_unit_args(int *argc, char ***argv);
int check_label(char *input);
int get_mountpt(char *dev, char *mntpt, size_t size);
int btrfs_scan_block_devices(int run_ioctl);
--
1.7.10.4
next reply other threads:[~2013-03-11 10:12 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-11 10:12 Audrius Butkevicius [this message]
2013-03-11 12:47 ` [PATCH] btrfs-progs: add options for changing size representations Wang Shilong
2013-03-11 20:48 ` Mike Fleetwood
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130311101242.GA18346@gmail.com \
--to=audrius.butkevicius@elastichosts.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.