/*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Peter Holm * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include 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 \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) { /* EOF */ printf("hole #%d @ %ld, size=%jd\n", n, (intmax_t)hole, 0L); } close(fd); }