From 1e13f3671739e98f4e6d8531b9b22c93d24589f8 Mon Sep 17 00:00:00 2001
From: Luke Shumaker <lukeshu@beefcake.parabola.nu>
Date: Fri, 18 May 2018 12:51:36 -0400
Subject: pull strextentflags in to a function

---
 lib/extent-map.c     |  4 +--
 lib/extent-map.h     |  1 +
 lib/strextentflags.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+), 3 deletions(-)
 create mode 100644 lib/strextentflags.c

(limited to 'lib')

diff --git a/lib/extent-map.c b/lib/extent-map.c
index 297448c..ab9cfb0 100644
--- a/lib/extent-map.c
+++ b/lib/extent-map.c
@@ -8,8 +8,6 @@
 
 #include "extent-map.h"
 
-#define error(_exit_code, ...) do { error(0, __VA_ARGS__); if (_exit_code) return _exit_code; } while(0)
-
 int fiemap(int fd, uint32_t flags, int (*handle_extent)(struct fiemap_extent)) {
 		const size_t fm_size = sysconf(_SC_PAGESIZE);;
 	struct fiemap *fm = calloc(1, fm_size);
@@ -25,7 +23,7 @@ int fiemap(int fd, uint32_t flags, int (*handle_extent)(struct fiemap_extent)) {
 		};
 
 		if (ioctl(fd, FS_IOC_FIEMAP, fm) < 0)
-			error(EXIT_FAILURE, errno, "ioctl (FS_IOC_FIEMAP)");
+			return -errno;
 
 		for (size_t i = 0; i < fm->fm_extent_count; i++) {
 			int r = handle_extent(fm->fm_extents[i]);
diff --git a/lib/extent-map.h b/lib/extent-map.h
index 8b5e585..22ba483 100644
--- a/lib/extent-map.h
+++ b/lib/extent-map.h
@@ -2,3 +2,4 @@
 #include <linux/fiemap.h> /* for struct fiemap_extent */
 
 int fiemap(int fd, uint32_t flags, int (*handle_extent)(struct fiemap_extent));
+char *strextentflags(uint32_t flags);
diff --git a/lib/strextentflags.c b/lib/strextentflags.c
new file mode 100644
index 0000000..c053ce7
--- /dev/null
+++ b/lib/strextentflags.c
@@ -0,0 +1,92 @@
+#include <errno.h>        /* for errno */
+#include <error.h>        /* for error(3gnu) */
+#include <inttypes.h>     /* PRI* */
+#include <linux/fiemap.h> /* for FIEMAP_EXTENT_* */
+#include <stdbool.h>      /* for bool, true, false */
+#include <stdio.h>        /* sprintf(3p) */
+#include <stdlib.h>       /* for malloc(3p), EXIT_FAILURE */
+#include <string.h>       /* for strlen(3p), strcpy(3p) */
+
+#include "extent-map.h"
+
+struct flag {
+	char *name;
+	uint32_t value;
+	bool active;
+};
+
+char *strextentflags(uint32_t flags) {
+	struct flag known_flags[] = {
+		{"LAST", FIEMAP_EXTENT_LAST, false},
+		{"UNKNOWN", FIEMAP_EXTENT_UNKNOWN, false},
+		{"DELALLOC", FIEMAP_EXTENT_DELALLOC, false},
+		{"ENCODED", FIEMAP_EXTENT_ENCODED, false},
+		{"DATA_ENCRYPTED", FIEMAP_EXTENT_DATA_ENCRYPTED, false},
+		{"NOT_ALIGNED", FIEMAP_EXTENT_NOT_ALIGNED, false},
+		{"DATA_INLINE", FIEMAP_EXTENT_DATA_INLINE, false},
+		{"DATA_TAIL", FIEMAP_EXTENT_DATA_TAIL, false},
+		{"UNWRITTEN", FIEMAP_EXTENT_UNWRITTEN, false},
+		{"MERGED", FIEMAP_EXTENT_MERGED, false},
+		{"SHARED", FIEMAP_EXTENT_SHARED, false},
+	};
+	size_t flagstr_cap = 0;
+	for (size_t i = 0; i < sizeof(known_flags)/sizeof(known_flags[0]); i++) {
+		if (!(flags & known_flags[i].value))
+			continue;
+		known_flags[i].active = true;
+		flags ^= known_flags[i].value;
+		switch (known_flags[i].value) {
+		case FIEMAP_EXTENT_UNKNOWN:
+			if (flags & FIEMAP_EXTENT_DELALLOC) {
+				known_flags[i].name = "(UNKNOWN|DELALLOC)";
+				flags ^= FIEMAP_EXTENT_DELALLOC;
+			}
+			break;
+		case FIEMAP_EXTENT_ENCODED:
+			if (flags & FIEMAP_EXTENT_DATA_ENCRYPTED) {
+				known_flags[i].name = "(ENCODED|DATA_ENCRYPTED)";
+				flags ^= FIEMAP_EXTENT_DATA_ENCRYPTED;
+			}
+			break;
+		case FIEMAP_EXTENT_NOT_ALIGNED:
+			switch (flags & (FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_DATA_TAIL)) {
+			case FIEMAP_EXTENT_DATA_INLINE:
+				known_flags[i].name = "(NOT_ALIGNED|DATA_INLINE)";
+				flags ^= FIEMAP_EXTENT_DATA_INLINE;
+				break;
+			case FIEMAP_EXTENT_DATA_TAIL:
+				known_flags[i].name = "(NOT_ALIGNED|DATA_TAIL)";
+				flags ^= FIEMAP_EXTENT_DATA_TAIL;
+				break;
+			case FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_DATA_TAIL:
+				known_flags[i].name = "(NOT_ALIGNED|DATA_INLINE|DATA_TAIL)";
+				flags ^= FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_DATA_TAIL;
+				break;
+			}
+			break;
+		}
+		if (flagstr_cap)
+			flagstr_cap++;
+		flagstr_cap += strlen(known_flags[i].name);
+	}
+	if (flags)
+		flagstr_cap += (flagstr_cap ? 1 : 0) + 10;
+	char *flagstr = malloc(flagstr_cap+1);
+	if (!flagstr)
+		error(EXIT_FAILURE, errno, "malloc");
+	size_t flagstr_len = 0;
+	for (size_t i = 0; i < sizeof(known_flags)/sizeof(known_flags[0]); i++) {
+		if (!known_flags[i].active)
+			continue;
+		if (flagstr_len)
+			flagstr[flagstr_len++] = '|';
+		strcpy(&flagstr[flagstr_len], known_flags[i].name);
+		flagstr_len += strlen(known_flags[i].name);
+	}
+	if (flags) {
+		if (flagstr_len)
+			flagstr[flagstr_len++] = '|';
+		sprintf(&flagstr[flagstr_len], "0x%08"PRIx32, flags);
+	};
+	return flagstr;
+}
-- 
cgit v1.2.3-2-g168b