Skip to content

Commit fef24d6

Browse files
committed
Work around copy_file_range() bug in eCryptFs
When programs like ar.ape and compile.ape are run on eCryptFs partitions on Linux, copy_file_range() will fail with EINVAL which is wrong because eCryptFs which doesn't support this system call, should raise EOPNOTSUPP See #1305
1 parent 12cc2de commit fef24d6

File tree

5 files changed

+9
-3
lines changed

5 files changed

+9
-3
lines changed

libc/calls/copy_file_range.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ static void copy_file_range_init(void) {
8383
* @return number of bytes transferred, or -1 w/ errno
8484
* @raise EXDEV if source and destination are on different filesystems
8585
* @raise EBADF if `infd` or `outfd` aren't open files or append-only
86+
* @raise EOPNOTSUPP if filesystem doesn't support this operation
8687
* @raise EPERM if `fdout` refers to an immutable file on Linux
8788
* @raise ECANCELED if thread was cancelled in masked mode
8889
* @raise EINVAL if ranges overlap or `flags` is non-zero
90+
* @raise EINVAL on eCryptFs filesystems that have a bug
8991
* @raise EFBIG if `setrlimit(RLIMIT_FSIZE)` is exceeded
9092
* @raise EFAULT if one of the pointers memory is bad
9193
* @raise ERANGE if overflow happens computing ranges

libc/calls/sig.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,6 @@ textwindows void __sig_generate(int sig, int sic) {
424424
(1ull << (sig - 1))) {
425425
return;
426426
}
427-
BLOCK_SIGNALS;
428427
_pthread_lock();
429428
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
430429
pt = POSIXTHREAD_CONTAINER(e);
@@ -462,7 +461,6 @@ textwindows void __sig_generate(int sig, int sic) {
462461
atomic_fetch_or_explicit(__sig.process, 1ull << (sig - 1),
463462
memory_order_relaxed);
464463
}
465-
ALLOW_SIGNALS;
466464
}
467465

468466
static textwindows char *__sig_stpcpy(char *d, const char *s) {

libc/thread/pthread_tryjoin_np.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* if the thread called pthread_exit(), or `PTHREAD_CANCELED` if
3333
* pthread_cancel() destroyed the thread instead
3434
* @return 0 on success, or errno on error
35+
* @raise EBUSY if thread has not yet terminated
3536
* @raise ECANCELED if calling thread was cancelled in masked mode
3637
* @cancelationpoint
3738
* @returnserrno

tool/build/ar.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ static void CopyFileOrDie(const char *inpath, int infd, //
298298
if (got != -1) {
299299
exchanged = got;
300300
} else if (errno == EXDEV || // different partitions
301+
errno == EINVAL || // possible w/ ecryptfs
301302
errno == ENOSYS || // not linux or freebsd
302303
errno == ENOTSUP || // probably a /zip file
303304
errno == EOPNOTSUPP) { // technically the same

tool/build/compile.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,11 @@ bool MovePreservingDestinationInode(const char *from, const char *to) {
798798
rc = copy_file_range(fdin, 0, fdout, 0, remain, 0);
799799
if (rc != -1) {
800800
remain -= rc;
801-
} else if (errno == EXDEV || errno == ENOSYS) {
801+
} else if (errno == EXDEV || // different partitions
802+
errno == EINVAL || // possible w/ ecryptfs
803+
errno == ENOSYS || // not linux or freebsd
804+
errno == ENOTSUP || // no fs support for it
805+
errno == EOPNOTSUPP) {
802806
if (lseek(fdin, 0, SEEK_SET) == -1) {
803807
res = false;
804808
break;

0 commit comments

Comments
 (0)