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:
Justine Tunney 2023-08-16 15:53:06 -07:00
parent dc6c67256f
commit b76b2be2d0
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
47 changed files with 644 additions and 269 deletions

View file

@ -47,14 +47,16 @@ int accept4(int fd, struct sockaddr *opt_out_addr, uint32_t *opt_inout_addrsize,
struct sockaddr_storage ss = {0};
BEGIN_CANCELLATION_POINT;
if (IsWindows()) {
if (__isfdkind(fd, kFdSocket)) {
rc = sys_accept_nt(g_fds.p + fd, &ss, flags);
} else {
rc = ebadf();
}
} else {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_accept4(fd, &ss, flags);
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_accept_nt(g_fds.p + fd, &ss, flags);
} else {
rc = enotsock();
}
if (rc != -1) {

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
@ -50,12 +51,16 @@ int bind(int fd, const struct sockaddr *addr, uint32_t addrsize) {
if (!addr || (IsAsan() && !__asan_is_valid(addr, addrsize))) {
rc = efault();
} else if (addrsize >= sizeof(struct sockaddr_in)) {
if (!IsWindows()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_bind(fd, addr, addrsize);
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_bind_nt(&g_fds.p[fd], addr, addrsize);
} else {
rc = ebadf();
rc = enotsock();
}
} else {
rc = einval();

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/cp.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
@ -45,12 +46,16 @@ int connect(int fd, const struct sockaddr *addr, uint32_t addrsize) {
BEGIN_CANCELLATION_POINT;
if (addr && !(IsAsan() && !__asan_is_valid(addr, addrsize))) {
if (!IsWindows()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_connect(fd, addr, addrsize);
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_connect_nt(&g_fds.p[fd], addr, addrsize);
} else {
rc = ebadf();
rc = enotsock();
}
} else {
rc = efault();

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
@ -45,18 +46,22 @@ int getsockopt(int fd, int level, int optname, void *out_opt_optval,
int rc;
if (level == -1 || !optname) {
rc = enoprotoopt(); /* see libc/sysv/consts.sh */
rc = enoprotoopt(); // see libc/sysv/consts.sh
} else if (IsAsan() && (out_opt_optval && out_optlen &&
(!__asan_is_valid(out_optlen, sizeof(uint32_t)) ||
!__asan_is_valid(out_opt_optval, *out_optlen)))) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_getsockopt(fd, level, optname, out_opt_optval, out_optlen);
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_getsockopt_nt(&g_fds.p[fd], level, optname, out_opt_optval,
out_optlen);
} else {
rc = ebadf();
rc = enotsock();
}
#ifdef SYSDEBUG

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sock/internal.h"
@ -37,12 +38,16 @@
*/
int listen(int fd, int backlog) {
int rc;
if (!IsWindows()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_listen(fd, backlog);
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_listen_nt(&g_fds.p[fd], backlog);
} else {
rc = ebadf();
rc = enotsock();
}
STRACE("listen(%d, %d) → %d% lm", fd, backlog, rc);
return rc;

View file

@ -47,6 +47,8 @@ ssize_t recv(int fd, void *buf, size_t size, int flags) {
if (IsAsan() && !__asan_is_valid(buf, size)) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_recvfrom(fd, buf, size, flags, 0, 0);
} else if (__isfdopen(fd)) {

View file

@ -62,6 +62,8 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
if (IsAsan() && !__asan_is_valid(buf, size)) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_recvfrom(fd, buf, size, flags, &addr, &addrsize);
} else if (__isfdopen(fd)) {

View file

@ -19,6 +19,7 @@
#include "libc/assert.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/dce.h"
@ -54,6 +55,8 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) {
BEGIN_CANCELLATION_POINT;
if (IsAsan() && !__asan_is_valid_msghdr(msg)) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
if (IsBsd() && msg->msg_name) {
memcpy(&msg2, msg, sizeof(msg2));

View file

@ -48,6 +48,8 @@ ssize_t send(int fd, const void *buf, size_t size, int flags) {
if (IsAsan() && !__asan_is_valid(buf, size)) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_sendto(fd, buf, size, flags, 0, 0);
} else if (__isfdopen(fd)) {

View file

@ -19,6 +19,7 @@
#include "libc/assert.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/dce.h"
@ -56,6 +57,8 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
BEGIN_CANCELLATION_POINT;
if (IsAsan() && !__asan_is_valid_msghdr(msg)) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
if (IsBsd() && msg->msg_name) {
memcpy(&msg2, msg, sizeof(msg2));

View file

@ -64,31 +64,31 @@ ssize_t sendto(int fd, const void *buf, size_t size, int flags,
if (IsAsan() && (!__asan_is_valid(buf, size) ||
(opt_addr && !__asan_is_valid(opt_addr, addrsize)))) {
rc = efault();
} else {
if (!IsWindows()) {
if (!IsBsd() || !opt_addr) {
rc = sys_sendto(fd, buf, size, flags, opt_addr, addrsize);
} else if (!(rc = sockaddr2bsd(opt_addr, addrsize, &bsd, &bsdaddrsize))) {
rc = sys_sendto(fd, buf, size, flags, &bsd, bsdaddrsize);
}
} else if (__isfdopen(fd)) {
if (__isfdkind(fd, kFdSocket)) {
rc = sys_sendto_nt(fd, (struct iovec[]){{buf, size}}, 1, flags,
opt_addr, addrsize);
} else if (__isfdkind(fd, kFdFile)) {
if (flags) {
rc = einval();
} else if (opt_addr) {
rc = eisconn();
} else {
rc = sys_write_nt(fd, (struct iovec[]){{buf, size}}, 1, -1);
}
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
if (!IsBsd() || !opt_addr) {
rc = sys_sendto(fd, buf, size, flags, opt_addr, addrsize);
} else if (!(rc = sockaddr2bsd(opt_addr, addrsize, &bsd, &bsdaddrsize))) {
rc = sys_sendto(fd, buf, size, flags, &bsd, bsdaddrsize);
}
} else if (__isfdopen(fd)) {
if (__isfdkind(fd, kFdSocket)) {
rc = sys_sendto_nt(fd, (struct iovec[]){{buf, size}}, 1, flags, opt_addr,
addrsize);
} else if (__isfdkind(fd, kFdFile)) {
if (flags) {
rc = einval();
} else if (opt_addr) {
rc = eisconn();
} else {
rc = enotsock();
rc = sys_write_nt(fd, (struct iovec[]){{buf, size}}, 1, -1);
}
} else {
rc = ebadf();
rc = enotsock();
}
} else {
rc = ebadf();
}
END_CANCELLATION_POINT;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -61,10 +62,12 @@ int setsockopt(int fd, int level, int optname, const void *optval,
int e, rc;
if (level == -1 || !optname) {
rc = enoprotoopt(); /* see libc/sysv/consts.sh */
rc = enoprotoopt(); // see libc/sysv/consts.sh
} else if ((!optval && optlen) ||
(IsAsan() && !__asan_is_valid(optval, optlen))) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = -1;
e = errno;
@ -75,10 +78,12 @@ int setsockopt(int fd, int level, int optname, const void *optval,
break;
}
} while (setsockopt_polyfill(&optname));
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_setsockopt_nt(&g_fds.p[fd], level, optname, optval, optlen);
} else {
rc = ebadf();
rc = enotsock();
}
#ifdef SYSDEBUG

View file

@ -35,12 +35,16 @@
*/
int shutdown(int fd, int how) {
int rc;
if (!IsWindows()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
rc = sys_shutdown(fd, how);
} else if (!__isfdopen(fd)) {
rc = ebadf();
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_shutdown_nt(&g_fds.p[fd], how);
} else {
rc = ebadf();
rc = enotsock();
}
STRACE("shutdown(%d, %d) -> %d% lm", fd, how, rc);
return rc;

View file

@ -54,7 +54,9 @@ int sockatmark(int fd) {
} else { //
magnum = 0x40047307; // SIOCATMARK (BSD, Windows)
}
if (!IsWindows()) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotsock();
} else if (!IsWindows()) {
if (sys_ioctl(fd, magnum, &rc) == -1) {
rc = -1;
}