Created
March 29, 2019 16:37
-
-
Save kostikbel/a4f9c80a7699151e7f2e5ba051740aa7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* $Id: seek_hole2.c,v 1.1 2012/05/26 04:50:17 kostik Exp kostik $ */ | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
static int | |
make_sparse(const char *name) | |
{ | |
int fd = open (name, O_RDWR | O_CREAT | O_TRUNC, 0600); | |
if (fd < 0) | |
return fd; | |
printf ("creating %s\n", name); | |
if (write (fd, "a", 1) != 1) | |
goto cleanup; | |
if (lseek (fd, 1024*1024, SEEK_CUR) == -1) | |
goto cleanup; | |
if (write (fd, "b", 1) != 1) | |
goto cleanup; | |
if (lseek (fd, 0, SEEK_SET) != 0) | |
goto cleanup; | |
return fd; | |
cleanup: | |
close (fd); | |
return -1; | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
off_t off; | |
off_t end; | |
int fd = argc > 2 ? open (argv[1], O_RDONLY) | |
: make_sparse (argc > 1 ? argv[1] : "file"); | |
perror(NULL); | |
if (fd < 0) | |
return 2; | |
printf ("fpathconf gives %ld, ENXIO is %d\n", | |
fpathconf (fd, _PC_MIN_HOLE_SIZE), ENXIO); | |
puts ("\ntesting at start"); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_HOLE); | |
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_DATA); | |
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_HOLE); | |
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
puts ("\ntesting at end"); | |
errno = 0; | |
off = end = lseek (fd, 0, SEEK_END); | |
printf ("end at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, end, SEEK_HOLE); | |
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, end, SEEK_DATA); | |
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, end - 1, SEEK_HOLE); | |
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, end - 1, SEEK_DATA); | |
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
puts ("\ntesting at offset 1"); | |
errno = 0; | |
off = lseek (fd, 1, SEEK_HOLE); | |
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 1, SEEK_DATA); | |
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
puts ("\ntesting at offset 200000"); | |
errno = 0; | |
off = lseek (fd, 200000, SEEK_HOLE); | |
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 200000, SEEK_DATA); | |
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno); | |
errno = 0; | |
off = lseek (fd, 0, SEEK_CUR); | |
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno); | |
if (close (fd)) | |
return 3; | |
return 0; | |
} | |
/* | |
Weblkml.org | |
Date Fri, 22 Apr 2011 05:41:47 -0600 | |
From Eric Blake <> | |
Subject Re: [PATCH 1/2] fs: add SEEK_HOLE and SEEK_DATA flags | |
On 04/21/2011 07:22 PM, Josef Bacik wrote: | |
>> You absolutely need to match Solaris semantics, which are documented as follows: | |
>> | |
>> � If whence is SEEK_HOLE, the offset of the start of the next hole | |
>> greater than or equal to the supplied offset is returned. The def- | |
>> inition of a hole is provided near the end of the DESCRIPTION. | |
>> | |
>> Note that in that definition, SEEK_HOLE does _not_ reposition the file offset | |
>> (it returns the offset of the next hole, which might be at the end of the file | |
>> since all files have a virtual hole at the end, but leaves the position | |
>> unchanged). I'd have to write a test program on Solaris to see whether that | |
>> definition is actually true, or if it is a bug in the Solaris man page. | |
> | |
> lseek's purpose is to reposition the file position, so I'd imagine | |
> this is just a bug in the man page. | |
Confirmed that the Solaris man page is buggy and does not accurately | |
describe the semantics that are actually implemented. My testing showed: | |
lseek(fd, off, SEEK_HOLE) has four cases: | |
off < end, in data: repositions to the next hole as if by lseek(fd, | |
next_hole, SEEK_CUR); the next hole is guaranteed to exist, even if at | |
end of file | |
off < end, in hole, and later in file has data: repositions as if by | |
lseek(fd, off, SEEK_CUR) | |
off < end, in hole, and no further data in file: repositions as if by | |
lseek(fd, 0, SEEK_END) | |
off == end: fails with ENXIO | |
lseek(fd, off, SEEK_DATA) has four cases: | |
off < end, in data: repositions as if by lseek(fd, off, SEEK_CUR) | |
off < end, in hole, and later in file has data: repositions to the next | |
data as if by lseek(fd, next_data, SEEK_CUR) | |
off < end, in hole, and remainder of file is hold: fails with ENXIO | |
off == end: fails with ENXIO | |
Here's how I tested: | |
$ ./foo | |
creating file | |
Error 0 | |
fpathconf gives 512, ENXIO is 6 | |
testing at start | |
CUR at offset 0, errno 0 | |
HOLE gives offset 131072, errno 0 | |
CUR at offset 131072, errno 0 | |
DATA gives offset 0, errno 0 | |
CUR at offset 0, errno 0 | |
HOLE gives offset 131072, errno 0 | |
CUR at offset 131072, errno 0 | |
testing at end | |
end at offset 1048578, errno 0 | |
HOLE gives offset -1, errno 6 | |
CUR at offset 1048578, errno 0 | |
DATA gives offset -1, errno 6 | |
CUR at offset 1048578, errno 0 | |
HOLE gives offset 1048578, errno 0 | |
CUR at offset 1048578, errno 0 | |
DATA gives offset 1048577, errno 0 | |
CUR at offset 1048577, errno 0 | |
testing at offset 1 | |
HOLE gives offset 131072, errno 0 | |
CUR at offset 131072, errno 0 | |
DATA gives offset 1, errno 0 | |
CUR at offset 1, errno 0 | |
testing at offset 200000 | |
HOLE gives offset 200000, errno 0 | |
CUR at offset 200000, errno 0 | |
DATA gives offset 1048576, errno 0 | |
CUR at offset 1048576, errno 0 | |
$ gtruncate -s 1M sparse | |
$ ./foo sparse 2 | |
Error 0 | |
fpathconf gives 512, ENXIO is 6 | |
testing at start | |
CUR at offset 0, errno 0 | |
HOLE gives offset 0, errno 0 | |
CUR at offset 0, errno 0 | |
DATA gives offset -1, errno 6 | |
CUR at offset 0, errno 0 | |
HOLE gives offset 0, errno 0 | |
CUR at offset 0, errno 0 | |
testing at end | |
end at offset 1048576, errno 0 | |
HOLE gives offset -1, errno 6 | |
CUR at offset 1048576, errno 0 | |
DATA gives offset -1, errno 6 | |
CUR at offset 1048576, errno 0 | |
HOLE gives offset 1048576, errno 0 | |
CUR at offset 1048576, errno 0 | |
DATA gives offset -1, errno 6 | |
CUR at offset 1048576, errno 0 | |
testing at offset 1 | |
HOLE gives offset 1, errno 0 | |
CUR at offset 1, errno 0 | |
DATA gives offset -1, errno 6 | |
CUR at offset 1, errno 0 | |
testing at offset 200000 | |
HOLE gives offset 1048576, errno 0 | |
CUR at offset 1048576, errno 0 | |
DATA gives offset -1, errno 6 | |
CUR at offset 1048576, errno 0 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment