Skip to content

Commit bd13204

Browse files
committed
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.
1 parent 0345a38 commit bd13204

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

src/posix.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,35 @@ int p_fallocate(int fd, off_t offset, off_t len)
159159
{
160160
#ifdef __APPLE__
161161
fstore_t prealloc;
162+
struct stat st;
163+
size_t newsize;
164+
int error;
165+
166+
if ((error = p_fstat(fd, &st)) < 0)
167+
return error;
168+
169+
if (git__add_sizet_overflow(&newsize, offset, len)) {
170+
errno = EINVAL;
171+
return -1;
172+
}
173+
174+
if (newsize < (unsigned long long)st.st_size)
175+
return 0;
162176

163177
memset(&prealloc, 0, sizeof(prealloc));
164178
prealloc.fst_flags = F_ALLOCATEALL;
165179
prealloc.fst_posmode = F_PEOFPOSMODE;
166180
prealloc.fst_offset = offset;
167181
prealloc.fst_length = len;
168182

169-
return fcntl(fd, F_PREALLOCATE, &prealloc);
183+
/*
184+
* fcntl will often error when the file already exists; ignore
185+
* this error since ftruncate will also resize the file (although
186+
* likely slower).
187+
*/
188+
fcntl(fd, F_PREALLOCATE, &prealloc);
189+
190+
return ftruncate(fd, (offset + len));
170191
#else
171192
return posix_fallocate(fd, offset, len);
172193
#endif

0 commit comments

Comments
 (0)