[PATCH] btrfs-progs: add options for changing size representations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxx>
---
 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

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


[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux