#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
struct stat st;
off_t data, hole, pos;
long mn;
intmax_t siz;
int fd, n;
char *name;
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
exit(1);
}
name = argv[1];
if ((fd = open(name, O_RDONLY)) == -1)
err(1, "open(%s)", name);
if (fstat(fd, &st))
err(1, "fstat()");
if ((mn = fpathconf(fd, _PC_MIN_HOLE_SIZE)) == -1)
err(1, "fpathconf()");
fprintf(stderr, "Min hole size is %ld, file size is %jd.\n",
mn, (intmax_t)st.st_size);
n = 1;
pos = 0;
while (pos < st.st_size) {
hole = lseek(fd, pos, SEEK_HOLE);
if (hole == -1 && errno != ENXIO)
err(1, "lseek(SEEK_HOLE)");
data = lseek(fd, pos, SEEK_DATA);
if (data == -1 && errno != ENXIO)
err(1, "lseek(SEEK_data)");
if (hole >= 0 && data >= 0 && hole > data) {
siz = hole - data;
printf("data #%d @ %ld, size=%jd)\n",
n, (intmax_t)data, siz);
n++;
pos += siz;
}
if (hole >= 0 && data >= 0 && hole < data) {
siz = data - hole;
printf("hole #%d @ %ld, size=%jd\n",
n, (intmax_t)hole, siz);
n++;
pos += siz;
}
if (hole >= 0 && data == -1) {
siz = st.st_size - hole;
printf("hole #%d @ %ld, size=%jd\n",
n, (intmax_t)hole, siz);
n++;
pos += siz;
}
}
if (hole == st.st_size) {
printf("hole #%d @ %ld, size=%jd\n",
n, (intmax_t)hole, 0L);
}
close(fd);
}