diff options
Diffstat (limited to 'tools-util.h')
-rw-r--r-- | tools-util.h | 120 |
1 files changed, 116 insertions, 4 deletions
diff --git a/tools-util.h b/tools-util.h index 09f00ef..1aac56a 100644 --- a/tools-util.h +++ b/tools-util.h @@ -5,21 +5,31 @@ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <linux/bug.h> #include <linux/byteorder.h> #include <linux/kernel.h> #include <linux/log2.h> #include <linux/string.h> #include <linux/types.h> +#include "ccan/darray/darray.h" -#define die(arg, ...) \ -do { \ - fprintf(stderr, arg "\n", ##__VA_ARGS__); \ - exit(EXIT_FAILURE); \ +#define die(arg, ...) \ +do { \ + fprintf(stderr, arg "\n", ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ } while (0) +#define mprintf(...) \ +({ \ + char *_str; \ + asprintf(&_str, __VA_ARGS__); \ + _str; \ +}) + static inline void *xcalloc(size_t count, size_t size) { void *p = calloc(count, size); @@ -57,6 +67,38 @@ static inline void xpwrite(int fd, const void *buf, size_t count, off_t offset) die("write error (ret %zi err %s)", r, strerror(errno)); } +#define xopenat(_dirfd, _path, ...) \ +({ \ + int _fd = openat((_dirfd), (_path), __VA_ARGS__); \ + if (_fd < 0) \ + die("Error opening %s: %s", (_path), strerror(errno)); \ + _fd; \ +}) + +#define xopen(...) xopenat(AT_FDCWD, __VA_ARGS__) + +static inline struct stat xfstatat(int dirfd, const char *path, int flags) +{ + struct stat stat; + if (fstatat(dirfd, path, &stat, flags)) + die("stat error: %s", strerror(errno)); + return stat; +} + +static inline struct stat xfstat(int fd) +{ + struct stat stat; + if (fstat(fd, &stat)) + die("stat error: %s", strerror(errno)); + return stat; +} + +#define xioctl(_fd, _nr, ...) \ +do { \ + if (ioctl((_fd), (_nr), ##__VA_ARGS__)) \ + die(#_nr " ioctl error: %s", strerror(errno)); \ +} while (0) + enum units { BYTES, SECTORS, @@ -91,4 +133,74 @@ struct bcache_handle bcache_fs_open(const char *); bool ask_yn(void); +struct range { + u64 start; + u64 end; +}; + +typedef darray(struct range) ranges; + +static inline void range_add(ranges *data, u64 offset, u64 size) +{ + darray_append(*data, (struct range) { + .start = offset, + .end = offset + size + }); +} + +void ranges_sort_merge(ranges *); +void ranges_roundup(ranges *, unsigned); +void ranges_rounddown(ranges *, unsigned); + +struct hole_iter { + ranges r; + size_t idx; + u64 end; +}; + +static inline struct range hole_iter_next(struct hole_iter *iter) +{ + struct range r = { + .start = iter->idx ? iter->r.item[iter->idx - 1].end : 0, + .end = iter->idx < iter->r.size + ? iter->r.item[iter->idx].start : iter->end, + }; + + BUG_ON(r.start > r.end); + + iter->idx++; + return r; +} + +#define for_each_hole(_iter, _ranges, _end, _i) \ + for (_iter = (struct hole_iter) { .r = _ranges, .end = _end }; \ + (_iter.idx <= _iter.r.size && \ + (_i = hole_iter_next(&_iter), true));) + +#include <linux/fiemap.h> + +struct fiemap_iter { + struct fiemap f; + struct fiemap_extent fe[1024]; + unsigned idx; + int fd; +}; + +static inline void fiemap_iter_init(struct fiemap_iter *iter, int fd) +{ + memset(iter, 0, sizeof(*iter)); + + iter->f.fm_extent_count = ARRAY_SIZE(iter->fe); + iter->f.fm_length = FIEMAP_MAX_OFFSET; + iter->fd = fd; +} + +struct fiemap_extent fiemap_iter_next(struct fiemap_iter *); + +#define fiemap_for_each(fd, iter, extent) \ + for (fiemap_iter_init(&iter, fd); \ + (extent = fiemap_iter_next(&iter)).fe_length;) + +const char *strcmp_prefix(const char *, const char *); + #endif /* _TOOLS_UTIL_H */ |