mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-26 22:38:30 +00:00
Improve zip read-only filesystem
readdir() will now always yield an inode that's consistent with stat() on ZipOS and Windows in general. More APIs have been updated to return the appropriate error code when inappropriately trying to do ops, like sockets, with a zip file descriptor. The path normalization algorithms are now fully fleshed out. Some socket APIs have been fixed so they'll raise EBADF vs. ENOTSOCK appropriately. Lastly seekdir() will now work properly on NetBSD and FreeBSD (not sure why anyone would even use it)
This commit is contained in:
parent
dc6c67256f
commit
b76b2be2d0
47 changed files with 644 additions and 269 deletions
|
@ -84,7 +84,6 @@ static void copy_file_range_init(void) {
|
|||
* @raise EXDEV if source and destination are on different filesystems
|
||||
* @raise EBADF if `infd` or `outfd` aren't open files or append-only
|
||||
* @raise EPERM if `fdout` refers to an immutable file on Linux
|
||||
* @raise ENOTSUP if `infd` or `outfd` is a zip file descriptor
|
||||
* @raise ECANCELED if thread was cancelled in masked mode
|
||||
* @raise EINVAL if ranges overlap or `flags` is non-zero
|
||||
* @raise EFBIG if `setrlimit(RLIMIT_FSIZE)` is exceeded
|
||||
|
@ -114,8 +113,10 @@ ssize_t copy_file_range(int infd, int64_t *opt_in_out_inoffset, int outfd,
|
|||
(opt_in_out_outoffset &&
|
||||
!__asan_is_valid(opt_in_out_outoffset, 8)))) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(infd, kFdZip) || __isfdkind(outfd, kFdZip)) {
|
||||
rc = enotsup();
|
||||
} else if (__isfdkind(outfd, kFdZip)) {
|
||||
rc = ebadf();
|
||||
} else if (__isfdkind(infd, kFdZip)) {
|
||||
rc = exdev();
|
||||
} else {
|
||||
rc = sys_copy_file_range(infd, opt_in_out_inoffset, outfd,
|
||||
opt_in_out_outoffset, uptobytes, flags);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/statfs-meta.internal.h"
|
||||
#include "libc/calls/struct/statfs.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -28,7 +29,9 @@
|
|||
|
||||
/**
|
||||
* Returns information about filesystem.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOTSUP if /zip path
|
||||
* @cancellationpoint
|
||||
*/
|
||||
int fstatfs(int fd, struct statfs *sf) {
|
||||
|
@ -37,7 +40,9 @@ int fstatfs(int fd, struct statfs *sf) {
|
|||
BEGIN_CANCELLATION_POINT;
|
||||
CheckLargeStackAllocation(&m, sizeof(m));
|
||||
|
||||
if (!IsWindows()) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotsup();
|
||||
} else if (!IsWindows()) {
|
||||
if ((rc = sys_fstatfs(fd, &m)) != -1) {
|
||||
statfs2cosmo(sf, &m);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||
int e, i;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
|
@ -59,6 +60,8 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = ebadf();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
} else if (__isfdkind(fd, kFdFile)) {
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
||||
int64_t off) {
|
||||
|
@ -51,8 +50,7 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
|||
}
|
||||
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return _weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
|
|
|
@ -18,29 +18,39 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/statfs-meta.internal.h"
|
||||
#include "libc/calls/struct/statfs.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns information about filesystem.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ECANCELED if thread was cancelled in masked mode
|
||||
* @raise EINTR if signal was delivered
|
||||
* @raise ENOTSUP if /zip path
|
||||
* @cancellationpoint
|
||||
*/
|
||||
int statfs(const char *path, struct statfs *sf) {
|
||||
int rc;
|
||||
union statfs_meta m;
|
||||
struct ZiposUri zipname;
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
|
||||
CheckLargeStackAllocation(&m, sizeof(m));
|
||||
if (!IsWindows()) {
|
||||
if (_weaken(__zipos_parseuri) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
rc = enotsup();
|
||||
} else if (!IsWindows()) {
|
||||
if ((rc = sys_statfs(path, &m)) != -1) {
|
||||
statfs2cosmo(sf, &m);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Syncs filesystem associated with file descriptor.
|
||||
|
@ -30,8 +32,13 @@
|
|||
* @raise ENOSPC if disk space was exhausted during sync
|
||||
* @raise EDQUOT (or ENOSPC) on some kinds of NFS errors
|
||||
* @raise EBADF if `fd` isn't a valid file descriptor
|
||||
* @raise EROFS if `fd` is a zip file
|
||||
* @raise ENOSYS on non-Linux
|
||||
*/
|
||||
int syncfs(int fd) {
|
||||
return sys_syncfs(fd);
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return erofs();
|
||||
} else {
|
||||
return sys_syncfs(fd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
|
@ -54,7 +55,9 @@ static dontinline textwindows int sys_tcdrain_nt(int fd) {
|
|||
int tcdrain(int fd) {
|
||||
int rc;
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
if (IsLinux()) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_ioctl_cp(fd, TCSBRK, (uintptr_t)1);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_ioctl_cp(fd, TIOCDRAIN, 0);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
|
@ -127,7 +128,9 @@ static dontinline textwindows int sys_tcflow_nt(int fd, int action) {
|
|||
*/
|
||||
int tcflow(int fd, int action) {
|
||||
int rc;
|
||||
if (IsLinux()) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCXONC, action);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_tcflow_bsd(fd, action);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
|
@ -76,7 +77,9 @@ static dontinline textwindows int sys_tcflush_nt(int fd, int queue) {
|
|||
*/
|
||||
int tcflush(int fd, int queue) {
|
||||
int rc;
|
||||
if (IsLinux()) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCFLSH, queue);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_ioctl(fd, TIOCFLUSH, &queue);
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define TIOCGSID (IsLinux() ? 0x5429 : 0x40047463)
|
||||
|
||||
|
@ -28,7 +30,11 @@
|
|||
*/
|
||||
int tcgetsid(int fd) {
|
||||
int rc, sid;
|
||||
rc = sys_ioctl(fd, TIOCGSID, &sid);
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else {
|
||||
rc = sys_ioctl(fd, TIOCGSID, &sid);
|
||||
}
|
||||
STRACE("tcgetsid(%d) → %d% m", fd, rc);
|
||||
return rc != -1 ? sid : -1;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,9 @@ static textwindows int sys_tcsendbreak_nt(int fd) {
|
|||
*/
|
||||
int tcsendbreak(int fd, int duration) {
|
||||
int rc;
|
||||
if (IsLinux()) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCSBRK, 0);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_tcsendbreak_bsd(fd);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -39,7 +40,9 @@
|
|||
*/
|
||||
int tcsetpgrp(int fd, int pgrp) {
|
||||
int rc;
|
||||
if (IsWindows() || IsMetal()) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsWindows() || IsMetal()) {
|
||||
rc = enosys();
|
||||
} else {
|
||||
rc = sys_ioctl(fd, TIOCSPGRP, &pgrp);
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Writes data to file descriptor.
|
||||
|
@ -71,8 +71,8 @@ ssize_t write(int fd, const void *buf, size_t size) {
|
|||
if (fd >= 0) {
|
||||
if ((!buf && size) || (IsAsan() && !__asan_is_valid(buf, size))) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotsup();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = ebadf();
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_write(fd, buf, size);
|
||||
} else if (fd >= g_fds.n) {
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Writes data from multiple buffers.
|
||||
|
@ -59,8 +58,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = _weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
rc = ebadf();
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
if (iovlen == 1) {
|
||||
rc = sys_write(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue