mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
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 https://github.com/jart/cosmopolitan/discussions/1305
This commit is contained in:
parent
12cc2de22e
commit
fef24d622a
5 changed files with 9 additions and 3 deletions
|
@ -83,9 +83,11 @@ static void copy_file_range_init(void) {
|
||||||
* @return number of bytes transferred, or -1 w/ errno
|
* @return number of bytes transferred, or -1 w/ errno
|
||||||
* @raise EXDEV if source and destination are on different filesystems
|
* @raise EXDEV if source and destination are on different filesystems
|
||||||
* @raise EBADF if `infd` or `outfd` aren't open files or append-only
|
* @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 EPERM if `fdout` refers to an immutable file on Linux
|
||||||
* @raise ECANCELED if thread was cancelled in masked mode
|
* @raise ECANCELED if thread was cancelled in masked mode
|
||||||
* @raise EINVAL if ranges overlap or `flags` is non-zero
|
* @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 EFBIG if `setrlimit(RLIMIT_FSIZE)` is exceeded
|
||||||
* @raise EFAULT if one of the pointers memory is bad
|
* @raise EFAULT if one of the pointers memory is bad
|
||||||
* @raise ERANGE if overflow happens computing ranges
|
* @raise ERANGE if overflow happens computing ranges
|
||||||
|
|
|
@ -424,7 +424,6 @@ textwindows void __sig_generate(int sig, int sic) {
|
||||||
(1ull << (sig - 1))) {
|
(1ull << (sig - 1))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BLOCK_SIGNALS;
|
|
||||||
_pthread_lock();
|
_pthread_lock();
|
||||||
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
|
for (e = dll_first(_pthread_list); e; e = dll_next(_pthread_list, e)) {
|
||||||
pt = POSIXTHREAD_CONTAINER(e);
|
pt = POSIXTHREAD_CONTAINER(e);
|
||||||
|
@ -462,7 +461,6 @@ textwindows void __sig_generate(int sig, int sic) {
|
||||||
atomic_fetch_or_explicit(__sig.process, 1ull << (sig - 1),
|
atomic_fetch_or_explicit(__sig.process, 1ull << (sig - 1),
|
||||||
memory_order_relaxed);
|
memory_order_relaxed);
|
||||||
}
|
}
|
||||||
ALLOW_SIGNALS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows char *__sig_stpcpy(char *d, const char *s) {
|
static textwindows char *__sig_stpcpy(char *d, const char *s) {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
* if the thread called pthread_exit(), or `PTHREAD_CANCELED` if
|
* if the thread called pthread_exit(), or `PTHREAD_CANCELED` if
|
||||||
* pthread_cancel() destroyed the thread instead
|
* pthread_cancel() destroyed the thread instead
|
||||||
* @return 0 on success, or errno on error
|
* @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
|
* @raise ECANCELED if calling thread was cancelled in masked mode
|
||||||
* @cancelationpoint
|
* @cancelationpoint
|
||||||
* @returnserrno
|
* @returnserrno
|
||||||
|
|
|
@ -298,6 +298,7 @@ static void CopyFileOrDie(const char *inpath, int infd, //
|
||||||
if (got != -1) {
|
if (got != -1) {
|
||||||
exchanged = got;
|
exchanged = got;
|
||||||
} else if (errno == EXDEV || // different partitions
|
} else if (errno == EXDEV || // different partitions
|
||||||
|
errno == EINVAL || // possible w/ ecryptfs
|
||||||
errno == ENOSYS || // not linux or freebsd
|
errno == ENOSYS || // not linux or freebsd
|
||||||
errno == ENOTSUP || // probably a /zip file
|
errno == ENOTSUP || // probably a /zip file
|
||||||
errno == EOPNOTSUPP) { // technically the same
|
errno == EOPNOTSUPP) { // technically the same
|
||||||
|
|
|
@ -798,7 +798,11 @@ bool MovePreservingDestinationInode(const char *from, const char *to) {
|
||||||
rc = copy_file_range(fdin, 0, fdout, 0, remain, 0);
|
rc = copy_file_range(fdin, 0, fdout, 0, remain, 0);
|
||||||
if (rc != -1) {
|
if (rc != -1) {
|
||||||
remain -= rc;
|
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) {
|
if (lseek(fdin, 0, SEEK_SET) == -1) {
|
||||||
res = false;
|
res = false;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue