1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021 Peter Holm <pho@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/param.h>
29 #include <sys/stat.h>
30
31 #include <err.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37
38 int
main(int argc,char * argv[])39 main(int argc, char *argv[])
40 {
41 struct stat st;
42 off_t data, hole, pos;
43 long mn;
44 intmax_t siz;
45 int fd, n;
46 char *name;
47
48 if (argc != 2) {
49 fprintf(stderr, "Usage: %s <file>\n", argv[0]);
50 exit(1);
51 }
52
53 name = argv[1];
54 if ((fd = open(name, O_RDONLY)) == -1)
55 err(1, "open(%s)", name);
56 if (fstat(fd, &st))
57 err(1, "fstat()");
58 if ((mn = fpathconf(fd, _PC_MIN_HOLE_SIZE)) == -1)
59 err(1, "fpathconf()");
60 fprintf(stderr, "Min hole size is %ld, file size is %jd.\n",
61 mn, (intmax_t)st.st_size);
62 n = 1;
63 pos = 0;
64
65 while (pos < st.st_size) {
66 hole = lseek(fd, pos, SEEK_HOLE);
67 if (hole == -1 && errno != ENXIO)
68 err(1, "lseek(SEEK_HOLE)");
69 data = lseek(fd, pos, SEEK_DATA);
70 if (data == -1 && errno != ENXIO)
71 err(1, "lseek(SEEK_data)");
72
73 if (hole >= 0 && data >= 0 && hole > data) {
74 siz = hole - data;
75 printf("data #%d @ %ld, size=%jd)\n",
76 n, (intmax_t)data, siz);
77 n++;
78 pos += siz;
79 }
80 if (hole >= 0 && data >= 0 && hole < data) {
81 siz = data - hole;
82 printf("hole #%d @ %ld, size=%jd\n",
83 n, (intmax_t)hole, siz);
84 n++;
85 pos += siz;
86 }
87 if (hole >= 0 && data == -1) {
88 siz = st.st_size - hole;
89 printf("hole #%d @ %ld, size=%jd\n",
90 n, (intmax_t)hole, siz);
91 n++;
92 pos += siz;
93 }
94 }
95 if (hole == st.st_size) {
96 /* EOF */
97 printf("hole #%d @ %ld, size=%jd\n",
98 n, (intmax_t)hole, 0L);
99 }
100 close(fd);
101 }
102