]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/seek.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2013 SGI
14 static cmdinfo_t seek_cmd
;
21 " returns the next hole and/or data offset at or after the requested offset\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"
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"
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 */
43 /* values for flag variable */
44 #define SEEK_DFLAG (1 << 0)
45 #define SEEK_HFLAG (1 << 1)
46 #define SEEK_RFLAG (1 << 2)
48 /* indexes into the seekinfo array */
53 char *name
; /* display item name */
54 int seektype
; /* data or hole */
55 int mask
; /* compared for print and looping */
57 {"DATA", SEEK_DATA
, SEEK_DFLAG
},
58 {"HOLE", SEEK_HOLE
, SEEK_HFLAG
}
61 /* print item type and offset. catch special cases of eof and error */
72 printf("%s %lld EOF\n", type
,
75 printf("%s EOF\n", type
);
77 printf("ERR %lld ", (long long)start
);
78 fflush(stdout
); /* so the printf preceded the perror */
83 printf("%s %lld %lld\n", type
,
84 (long long)start
, (long long)offset
);
86 printf("%s %lld\n", type
, (long long)offset
);
95 off64_t offset
, start
;
96 size_t fsblocksize
, fssectsize
;
98 int current
; /* specify data or hole */
102 flag
= startflag
= 0;
103 init_cvtnum(&fsblocksize
, &fssectsize
);
105 while ((c
= getopt(argc
, argv
, "adhrs")) != EOF
) {
108 flag
|= (SEEK_HFLAG
| SEEK_DFLAG
);
123 return command_usage(&seek_cmd
);
126 if (!(flag
& (SEEK_DFLAG
| SEEK_HFLAG
)) || optind
!= argc
- 1)
127 return command_usage(&seek_cmd
);
129 start
= offset
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
131 return command_usage(&seek_cmd
);
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.
137 if (flag
& SEEK_HFLAG
) {
139 offset
= lseek(file
->fd
, start
, SEEK_HOLE
);
140 if (offset
!= -1 && offset
< start
)
142 if ((start
== offset
) || !(flag
& SEEK_DFLAG
)) {
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.
153 /* The offset is not a hole, or we are looking just for data */
155 offset
= lseek(file
->fd
, start
, SEEK_DATA
);
156 if (offset
!= -1 && offset
< start
)
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.
166 * An error or EOF will terminate the display, otherwise "flag"
167 * determines if there are more items to be displayed.
170 printf("Whence Start Result\n");
172 printf("Whence Result\n");
174 for (c
= 0; flag
; c
++) {
176 /* print error or eof if the only entry */
177 if (errno
!= ENXIO
|| c
== 0 )
178 seek_output(startflag
, seekinfo
[current
].name
,
180 return 0; /* stop on error or EOF */
183 if (flag
& seekinfo
[current
].mask
)
184 seek_output(startflag
, seekinfo
[current
].name
, start
,
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.
192 if (!(flag
& SEEK_RFLAG
))
193 flag
&= ~seekinfo
[current
].mask
;
195 current
^= 1; /* alternate between data and hole */
197 offset
= lseek(file
->fd
, start
, seekinfo
[current
].seektype
);
198 if (offset
!= -1 && offset
<= start
)
204 fprintf(stderr
, "Invalid seek result: lseek(<fd>, %lld, SEEK_%s) = %lld\n",
205 (long long)start
, seekinfo
[current
].name
, (long long)offset
);
212 seek_cmd
.name
= "seek";
213 seek_cmd
.cfunc
= seek_f
;
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
;
221 add_command(&seek_cmd
);