Does posix_fallocate work with files opened with added mode?

I am trying to reallocate disk space for file operations, however, I am faced with one strange problem: posix_fallocate only adds one byte when I call it to allocate disk space for files opened using add mode, and the file contents are also unexpected. Did anyone know this problem? And my test codes:


#include <cstdio> #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> #include <cerrno> int main(int argc, char **argv) { FILE *fp = fopen("append.txt", "w"); for (int i = 0; i < 5; ++i) fprintf(fp, "## Test loop %d\n", i); fclose(fp); sleep(1); int fid = open("append.txt", O_WRONLY | O_APPEND); struct stat status; fstat(fid, &status); printf("INFO: sizeof 'append.txt' is %ld Bytes.\n", status.st_size); int ret = posix_fallocate(fid, (off_t)status.st_size, 1024); if (ret) { switch (ret) { case EBADF: fprintf(stderr, "ERROR: %d is not a valid file descriptor, or is not opened for writing.\n", fid); break; case EFBIG: fprintf(stderr, "ERROR: exceed the maximum file size.\n"); break; case ENOSPC: fprintf(stderr, "ERROR: There is not enough space left on the device\n"); break; default: break; } } fstat(fid, &status); printf("INFO: sizeof 'append.txt' is %ld Bytes.\n", status.st_size); char *hello = "hello world\n"; write(fid, hello, 12); close(fid); return 0; } 

And the expected result should be,

 ## Test loop 0 ## Test loop 1 ## Test loop 2 ## Test loop 3 ## Test loop 4 hello world 

However, the result of the above program:

 ## Test loop 0 ## Test loop 1 ## Test loop 2 ## Test loop 3 ## Test loop 4 ^@hello world 

So what is "^ @"?

And the message shows

 INFO: sizeof 'append.txt' is 75 Bytes. INFO: sizeof 'append.txt' is 76 Bytes. 

Any clues?

thanks

+4
source share
2 answers

Quick response

Yes, posix_fallocate works with files opened in APPEND mode. If your file system supports the fallocate system call. If your file system does not support it, glibc emulation adds one 0 bytes to the end in APPEND mode.

Additional Information

It was strange and really puzzling me. I found the answer using strace , which shows which system calls are being made.

Check this:

fallocate (3, 0, 74, 1000) = -1 EOPNOTSUPP (operation not supported)
fstat (3, {st_mode = S_IFREG | 0664, st_size = 75, ...}) = 0
fstatfs (3, {f_type = 0xf15f, f_bsize = 4096, f_blocks = 56777565, f_bfree = 30435527, f_bavail = 27551380, f_files = 14426112, f_ffree = 13172614, f_fsid = {1863489073, -145639frs} ) = 0
pwrite (3, "\ 0", 1, 1073) = 1

The GNU C library seems to be trying to help you here. The fallocate system call does not seem to be implemented on your file system, so GLibC mimics it using pwrite to write 0 bytes at the end of the requested allocation, thereby expanding the file.

This works fine in normal recording mode. But in APPEND mode, writing is always done at the end of the file, so pwrite writes one byte at the end.

Not what was intended. Perhaps this is a GNU C library error.

Ext4 seems to support fallocate . And if I write the file in / tmp, it will work. It does not work in my home directory because I use an encrypted home directory in Ubuntu with the ecryptfs file system

+5
source

Per POSIX :

If offset + len is outside the current file size, then posix_fallocate () should set the file size to offset + len. Otherwise, the file size should not be changed.

Therefore, it makes no sense to use posix_fallocate with the add mode, since it expands the file size (it is filled with zero bytes), and subsequent writes will be performed after those zero bytes that are not already reserved.

As for why it only extends the file by one byte, are you sure this is correct? Have you measured This sounds like an implementation error.

+1
source

Source: https://habr.com/ru/post/1487386/


All Articles