Commit bd132046 by Edward Thomson

p_fallocate: compatibility fixes for macOS

On macOS, fcntl(..., F_PREALLOCATE, ...) will only succeed when followed
by an ftruncate(), even when it reports success.

However, that syscall will fail when the file already exists.  Thus, we
must ignore the error code and simply let ftruncate extend the size of
the file itself (albeit slowly).

By calling ftruncate, we also need to prevent against file shrinkage,
for compatibility with posix_ftruncate, which will only extend files,
never shrink them.
parent 0345a380
......@@ -159,6 +159,20 @@ int p_fallocate(int fd, off_t offset, off_t len)
{
#ifdef __APPLE__
fstore_t prealloc;
struct stat st;
size_t newsize;
int error;
if ((error = p_fstat(fd, &st)) < 0)
return error;
if (git__add_sizet_overflow(&newsize, offset, len)) {
errno = EINVAL;
return -1;
}
if (newsize < (unsigned long long)st.st_size)
return 0;
memset(&prealloc, 0, sizeof(prealloc));
prealloc.fst_flags = F_ALLOCATEALL;
......@@ -166,7 +180,14 @@ int p_fallocate(int fd, off_t offset, off_t len)
prealloc.fst_offset = offset;
prealloc.fst_length = len;
return fcntl(fd, F_PREALLOCATE, &prealloc);
/*
* fcntl will often error when the file already exists; ignore
* this error since ftruncate will also resize the file (although
* likely slower).
*/
fcntl(fd, F_PREALLOCATE, &prealloc);
return ftruncate(fd, (offset + len));
#else
return posix_fallocate(fd, offset, len);
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment