Skip to content

Commit

Permalink
Work around copy_file_range() bug in eCryptFs
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jart committed Sep 29, 2024
1 parent 12cc2de commit fef24d6
Show file tree
Hide file tree
Showing 5 changed files with 9 additions and 3 deletions.
2 changes: 2 additions & 0 deletions libc/calls/copy_file_range.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ static void copy_file_range_init(void) {
* @return number of bytes transferred, or -1 w/ errno
* @raise EXDEV if source and destination are on different filesystems
* @raise EBADF if `infd` or `outfd` aren't open files or append-only
* @raise EOPNOTSUPP if filesystem doesn't support this operation
* @raise EPERM if `fdout` refers to an immutable file on Linux
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EINVAL if ranges overlap or `flags` is non-zero
* @raise EINVAL on eCryptFs filesystems that have a bug
* @raise EFBIG if `setrlimit(RLIMIT_FSIZE)` is exceeded
* @raise EFAULT if one of the pointers memory is bad
* @raise ERANGE if overflow happens computing ranges
Expand Down
2 changes: 0 additions & 2 deletions libc/calls/sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,6 @@ textwindows void __sig_generate(int sig, int sic) {
(1ull << (sig - 1))) {
return;
}
BLOCK_SIGNALS;
_pthread_lock();
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
pt = POSIXTHREAD_CONTAINER(e);
Expand Down Expand Up @@ -462,7 +461,6 @@ textwindows void __sig_generate(int sig, int sic) {
atomic_fetch_or_explicit(__sig.process, 1ull << (sig - 1),
memory_order_relaxed);
}
ALLOW_SIGNALS;
}

static textwindows char *__sig_stpcpy(char *d, const char *s) {
Expand Down
1 change: 1 addition & 0 deletions libc/thread/pthread_tryjoin_np.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* if the thread called pthread_exit(), or `PTHREAD_CANCELED` if
* pthread_cancel() destroyed the thread instead
* @return 0 on success, or errno on error
* @raise EBUSY if thread has not yet terminated
* @raise ECANCELED if calling thread was cancelled in masked mode
* @cancelationpoint
* @returnserrno
Expand Down
1 change: 1 addition & 0 deletions tool/build/ar.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ static void CopyFileOrDie(const char *inpath, int infd, //
if (got != -1) {
exchanged = got;
} else if (errno == EXDEV || // different partitions
errno == EINVAL || // possible w/ ecryptfs
errno == ENOSYS || // not linux or freebsd
errno == ENOTSUP || // probably a /zip file
errno == EOPNOTSUPP) { // technically the same
Expand Down
6 changes: 5 additions & 1 deletion tool/build/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,11 @@ bool MovePreservingDestinationInode(const char *from, const char *to) {
rc = copy_file_range(fdin, 0, fdout, 0, remain, 0);
if (rc != -1) {
remain -= rc;
} else if (errno == EXDEV || errno == ENOSYS) {
} else if (errno == EXDEV || // different partitions
errno == EINVAL || // possible w/ ecryptfs
errno == ENOSYS || // not linux or freebsd
errno == ENOTSUP || // no fs support for it
errno == EOPNOTSUPP) {
if (lseek(fdin, 0, SEEK_SET) == -1) {
res = false;
break;
Expand Down

0 comments on commit fef24d6

Please sign in to comment.