#include /* for errno */ #include /* for error(3gnu) */ #include /* for all of the other fiemap stuff */ #include /* for FS_IOC_FIEMAP */ #include /* for calloc(3p), exit(3p), EXIT_SUCCESS, EXIT_FAILURE */ #include /* for ioctl(2) */ #include /* for sysconf(3p), _SC_PAGESIZE */ #include "extent-map.h" void 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); if (!fm) error(EXIT_FAILURE, errno, "malloc"); uint64_t bytes_mapped = 0; while (1) { *fm = (struct fiemap){ .fm_start = bytes_mapped, .fm_length = FIEMAP_MAX_OFFSET - bytes_mapped, .fm_flags = flags, .fm_extent_count = (fm_size - sizeof(struct fiemap)) / sizeof(struct fiemap_extent), }; if (ioctl(fd, FS_IOC_FIEMAP, fm) < 0) error(EXIT_FAILURE, errno, "ioctl (FS_IOC_FIEMAP)"); for (size_t i = 0; i < fm->fm_extent_count; i++) { int r = handle_extent(fm->fm_extents[i]); if (r) { free(fm); exit(r); } if (fm->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST) { free(fm); exit(EXIT_SUCCESS); } } } }