provide emulation of fcntl F_DUPFD_CLOEXEC on old kernels

I'm not entirely happy with the amount of ugliness here, but since
F_DUPFD_CLOEXEC is used elsewhere in code that's expected to work on
old kernels (popen), it seems necessary. reportedly even some modern
kernels went back and broke F_DUPFD_CLOEXEC (making it behave like
plain F_DUPFD), so it might be necessary to add some additional fixup
code later to deal with that issue too.
This commit is contained in:
Rich Felker
2013-03-26 22:54:57 -04:00
parent ae7399bfd8
commit 00f1521fdd

View File

@@ -22,5 +22,21 @@ int fcntl(int fd, int cmd, ...)
if (ret) return __syscall_ret(ret); if (ret) return __syscall_ret(ret);
return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid;
} }
if (cmd == F_DUPFD_CLOEXEC) {
int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
if (ret != -EINVAL) {
if (ret >= 0)
__syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
return __syscall_ret(ret);
}
ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0);
if (ret != -EINVAL) {
if (ret >= 0) __syscall(SYS_close, ret);
return __syscall_ret(-EINVAL);
}
ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg);
if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
return __syscall_ret(ret);
}
return syscall(SYS_fcntl, fd, cmd, arg); return syscall(SYS_fcntl, fd, cmd, arg);
} }