]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/seek.c
xfsprogs: make static things static
[thirdparty/xfsprogs-dev.git] / io / seek.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
b169249b
MT
2/*
3 * Copyright (c) 2013 SGI
4 * All Rights Reserved.
b169249b
MT
5 */
6
6b803e5a
CH
7#include "command.h"
8#include "input.h"
b169249b
MT
9#include <sys/types.h>
10#include <unistd.h>
11#include "init.h"
12#include "io.h"
13
14static cmdinfo_t seek_cmd;
15
16static void
17seek_help(void)
18{
19 printf(_(
20"\n"
21" returns the next hole and/or data offset at or after the requested offset\n"
22"\n"
23" Example:\n"
24" 'seek -d 512' - offset of data at or following offset 512\n"
25" 'seek -a -r 0' - offsets of all data and hole in entire file\n"
26"\n"
27" Returns the offset of the next data and/or hole. There is an implied hole\n"
28" at the end of file. If the specified offset is past end of file, or there\n"
29" is no data past the specified offset, EOF is returned.\n"
30" -a -- return the next data and hole starting at the specified offset.\n"
31" -d -- return the next data starting at the specified offset.\n"
32" -h -- return the next hole starting at the specified offset.\n"
33" -r -- return all remaining type(s) starting at the specified offset.\n"
34" -s -- also print the starting offset.\n"
35"\n"));
36}
37
38#ifndef HAVE_SEEK_DATA
39#define SEEK_DATA 3 /* seek to the next data */
40#define SEEK_HOLE 4 /* seek to the next hole */
41#endif
42
43/* values for flag variable */
44#define SEEK_DFLAG (1 << 0)
45#define SEEK_HFLAG (1 << 1)
46#define SEEK_RFLAG (1 << 2)
47
48/* indexes into the seekinfo array */
49#define DATA 0
50#define HOLE 1
51
00ff2b10 52static struct seekinfo {
b169249b
MT
53 char *name; /* display item name */
54 int seektype; /* data or hole */
55 int mask; /* compared for print and looping */
56} seekinfo[] = {
57 {"DATA", SEEK_DATA, SEEK_DFLAG},
58 {"HOLE", SEEK_HOLE, SEEK_HFLAG}
59};
60
61/* print item type and offset. catch special cases of eof and error */
00ff2b10 62static void
b169249b
MT
63seek_output(
64 int startflag,
65 char *type,
66 off64_t start,
67 off64_t offset)
68{
69 if (offset == -1) {
70 if (errno == ENXIO) {
71 if (startflag)
72 printf("%s %lld EOF\n", type,
73 (long long)start);
74 else
75 printf("%s EOF\n", type);
76 } else {
77 printf("ERR %lld ", (long long)start);
78 fflush(stdout); /* so the printf preceded the perror */
79 perror("");
80 }
81 } else {
82 if (startflag)
83 printf("%s %lld %lld\n", type,
84 (long long)start, (long long)offset);
85 else
86 printf("%s %lld\n", type, (long long)offset);
87 }
88}
89
90static int
91seek_f(
92 int argc,
93 char **argv)
94{
95 off64_t offset, start;
96 size_t fsblocksize, fssectsize;
97 int c;
98 int current; /* specify data or hole */
99 int flag;
100 int startflag;
101
102 flag = startflag = 0;
103 init_cvtnum(&fsblocksize, &fssectsize);
104
105 while ((c = getopt(argc, argv, "adhrs")) != EOF) {
106 switch (c) {
107 case 'a':
108 flag |= (SEEK_HFLAG | SEEK_DFLAG);
109 break;
110 case 'd':
111 flag |= SEEK_DFLAG;
112 break;
113 case 'h':
114 flag |= SEEK_HFLAG;
115 break;
116 case 'r':
117 flag |= SEEK_RFLAG;
118 break;
119 case 's':
120 startflag = 1;
121 break;
122 default:
123 return command_usage(&seek_cmd);
124 }
125 }
126 if (!(flag & (SEEK_DFLAG | SEEK_HFLAG)) || optind != argc - 1)
127 return command_usage(&seek_cmd);
128
129 start = offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
130 if (offset < 0)
131 return command_usage(&seek_cmd);
132
133 /*
134 * check to see if the offset is a data or hole entry and
135 * decide if we want to display that type of entry.
136 */
137 if (flag & SEEK_HFLAG) {
866d7fcb 138 current = HOLE;
dc8878f4 139 offset = lseek(file->fd, start, SEEK_HOLE);
866d7fcb
AG
140 if (offset != -1 && offset < start)
141 goto bad_result;
b169249b
MT
142 if ((start == offset) || !(flag & SEEK_DFLAG)) {
143 /*
144 * this offset is a hole or are only displaying holes.
145 * if this offset is for data and we are displaying
146 * data, then we will fall through below to
147 * initialize the data search.
148 */
b169249b
MT
149 goto found_hole;
150 }
151 }
152
153 /* The offset is not a hole, or we are looking just for data */
154 current = DATA;
dc8878f4 155 offset = lseek(file->fd, start, SEEK_DATA);
866d7fcb
AG
156 if (offset != -1 && offset < start)
157 goto bad_result;
b169249b
MT
158
159found_hole:
160 /*
161 * At this point we know which type and the offset of the starting
162 * item. "current" alternates between data / hole entries in
163 * assending order - this alternation is needed even if only one
164 * type is to be displayed.
165 *
166 * An error or EOF will terminate the display, otherwise "flag"
167 * determines if there are more items to be displayed.
168 */
169 if (startflag)
170 printf("Whence Start Result\n");
171 else
172 printf("Whence Result\n");
173
174 for (c = 0; flag; c++) {
175 if (offset == -1) {
176 /* print error or eof if the only entry */
177 if (errno != ENXIO || c == 0 )
178 seek_output(startflag, seekinfo[current].name,
179 start, offset);
180 return 0; /* stop on error or EOF */
181 }
182
183 if (flag & seekinfo[current].mask)
184 seek_output(startflag, seekinfo[current].name, start,
185 offset);
186
187 /*
188 * When displaying only a single data and/or hole item, mask
189 * off the item as it is displayed. The loop will end when all
190 * requested items have been displayed.
191 */
192 if (!(flag & SEEK_RFLAG))
193 flag &= ~seekinfo[current].mask;
194
195 current ^= 1; /* alternate between data and hole */
196 start = offset;
dc8878f4 197 offset = lseek(file->fd, start, seekinfo[current].seektype);
866d7fcb
AG
198 if (offset != -1 && offset <= start)
199 goto bad_result;
b169249b
MT
200 }
201 return 0;
866d7fcb
AG
202
203bad_result:
204 fprintf(stderr, "Invalid seek result: lseek(<fd>, %lld, SEEK_%s) = %lld\n",
205 (long long)start, seekinfo[current].name, (long long)offset);
206 return 0;
b169249b
MT
207}
208
209void
210seek_init(void)
211{
212 seek_cmd.name = "seek";
213 seek_cmd.cfunc = seek_f;
214 seek_cmd.argmin = 2;
215 seek_cmd.argmax = 5;
216 seek_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
217 seek_cmd.args = _("-a | -d | -h [-r] off");
218 seek_cmd.oneline = _("locate the next data and/or hole");
219 seek_cmd.help = seek_help;
220
221 add_command(&seek_cmd);
222}