SEEK_HOLE和SEEK_DATA在Ubuntu 12.04.2 LTS中不起作用

编译时我得到错误:

cc holetest.c -o holetest holetest.c: In function 'test_seek': holetest.c:48:19: error: 'SEEK_HOLE' undeclared (first use in this function) holetest.c:48:19: note: each undeclared identifier is reported only once for each function it appears in holetest.c:51:19: error: 'SEEK_DATA' undeclared (first use in this function) make: *** [holetest] Error 1 

如果我删除SEEK_HOLE和SEEK_DATA,我没有问题。

我错过了包含或图书馆吗?

Makefile文件:

 all: holetest holetest: holetest.c rm -f holetest gcc holetest.c -o holetest 

holetest.c:

 #include  #include  #include  #include  #include  #include  #include  #include  #define FILENAME "/tmp/partly.sparse" #define FILE_SIZE (1<<30) #define START_STRING "start of file\n" #define START_LEN strlen(START_STRING) #define END_STRING "\nend of file\n" #define END_LEN strlen(END_STRING) #define debug(M, ...) fprintf(stderr, "%i: DEBUG %10.10s:%3.0d: " M "\n", getpid(), __FILE__, __LINE__, ##__VA_ARGS__); fflush(stderr); #define log_err(M, ...) fprintf(stderr, "%i: ERROR errno:%i %10.10s:%3.0d: " M "\n", getpid(), errno, __FILE__, __LINE__, ##__VA_ARGS__); fflush(stderr); #define quit_if(COND, ...) do { \ if(COND) { \ log_err(__VA_ARGS__); \ perror(NULL); \ exit(errno); \ } \ } while(0); int make_partly_sparse(const char *filename, off_t size) { int r, fd; fd = open(filename, O_RDWR|O_CREAT, 0755); quit_if(fd < 1, "unable to create %s", filename); r = write(fd, START_STRING, START_LEN); quit_if(r < START_LEN, "unable to write %s", filename); r = lseek(fd, FILE_SIZE - END_LEN, SEEK_SET); quit_if(r < 0, "unable to seek %s", filename); r = write(fd, END_STRING, END_LEN); quit_if(r < END_LEN, "unable to write %s", filename); r = close(fd); quit_if(r < 0, "unable to close %s", filename); return 0; } int test_seek(const char *filename) { int r, fd; fd = open(filename, O_RDWR|O_CREAT, 0755); quit_if(fd < 1, "unable to open %s", filename); debug("seeking hole at %li", START_LEN); r = lseek(fd, 0, SEEK_HOLE); quit_if(r < 0, "unable to seek %s", filename); quit_if(r != START_LEN, "SEEK_HOLE unsupported %i", r); r = lseek(fd, 0, SEEK_DATA); quit_if(r < 0, "unable to seek %s", filename); quit_if(r != (FILE_SIZE - END_LEN), "SEEK_DATA unsupported %i", r); r = close(fd); quit_if(r < 0, "unable to close %s", filename); return 0; } int main(int argc, char *argv[]) { debug("making sparse file: %s", FILENAME); make_partly_sparse(FILENAME, FILE_SIZE); test_seek(FILENAME); return 0; } 

系统:

 $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=12.04 DISTRIB_CODENAME=precise DISTRIB_DESCRIPTION="Ubuntu 12.04.2 LTS" $ uname -a Linux tux 3.2.0-45-generic #70-Ubuntu SMP Wed May 29 20:12:06 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux $ grep "ext" /etc/fstab UUID=be3aacb3-6457-4ba1-92bb-0f63ad514f40 / ext4 errors=remount-ro 0 1 

更新:

它现在编译但不起作用,SEEK_HOLE跳过洞并寻找到文件的末尾。

 $ make rm -f holetest gcc -D_GNU_SOURCE holetest.c -o holetest $ ./holetest 18731: DEBUG holetest.c: 60: making sparse file: /tmp/partly.sparse 18731: DEBUG holetest.c: 47: seeking hole at 14 18731: ERROR errno:0 holetest.c: 50: SEEK_HOLE unsupported 1073741824 Success $ du /tmp/partly.sparse 8 /tmp/partly.sparse $ ls -lA /tmp/partly.sparse -rwxr-xr-x 1 chris chris 1073741824 Aug 16 14:08 /tmp/partly.sparse 

stdio.h将它们定义为;

 /* The possibilities for the third argument to `fseek'. These values should not be changed. */ #define SEEK_SET 0 /* Seek from beginning of file. */ #define SEEK_CUR 1 /* Seek from current position. */ #define SEEK_END 2 /* Seek from end of file. */ #ifdef __USE_GNU # define SEEK_DATA 3 /* Seek to next data. */ # define SEEK_HOLE 4 /* Seek to next hole. */ #endif 

__USE_GNU是在定义_GNU_SOURCE时设置的内部符号,这意味着要使用它们,您需要使用-D_GNU_SOURCE进行编译。

 $ gcc test.c test.c: In function 'test_seek': test.c:48:26: error: 'SEEK_HOLE' undeclared (first use in this function) test.c:48:26: note: each undeclared identifier is reported only once for each function it appears in test.c:51:26: error: 'SEEK_DATA' undeclared (first use in this function) $ gcc -D_GNU_SOURCE test.c $ 

您现在遇到的行为是允许的:来自lseek linux手册页 :

在最简单的实现中,文件系统可以通过使SEEK_HOLE始终返回文件末尾的偏移量来支持操作,并使SEEK_DATA始终返回偏移量(即,即使偏移量引用的位置是一个洞,它也可以是被认为是由零序列组成的数据。

请注意,lseek手册页说

但是,文件系统没有义务报告漏洞,因此这些操作不是用于映射实际分配给文件的存储空间的保证机制。

ext4文件系统中的SEEK_HOLE支持在3.8内核中被添加到linux中,Ubuntu 12.04使用的是比这更老的内核 – 你的内核版本是3.2.0-45。