2

コンパイルすると、次のエラーが表示されます。

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 を削除しても問題はありません。

インクルードまたはライブラリを見逃していませんか?

メイクファイル:

all: holetest

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

ホールテスト.c:

#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

#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
4

3 に答える 3

6

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 
$ 
于 2013-08-16T13:02:40.233 に答える
4

lseek マンページには次のように書かれていることに注意してください

ただし、ファイル システムはホールを報告する義務がないため、これらの操作は、ファイルに実際に割り当てられたストレージ領域をマッピングするための保証されたメカニズムではありません。

ext4 ファイルシステムでの SEEK_HOLE サポートは3.8 カーネルの linux に追加されました。Ubuntu 12.04 はそれよりも古いカーネルを使用しています - カーネルのバージョンは 3.2.0-45 です。

于 2013-08-16T13:35:45.793 に答える
2

現在発生している動作は許可されています: lseek linux manpageから:

最も単純な実装では、ファイル システムは、SEEK_HOLE が常にファイルの末尾のオフセットを返すようにし、SEEK_DATA が常にオフセットを返すようにすることで、操作をサポートできます (つまり、オフセットによって参照される場所がホールであっても、ゼロの連続であるデータで構成されていると見なされます)。

于 2013-08-16T13:22:20.907 に答える