mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-27 04:50:28 +00:00
Implement __zipos_dup (#972)
* Implement __zipos_dup Makes ZiposHandle reference-counted by an `rc` field in a union with its freelist `next` pointer. The functions `__zipos_free` and `__zipos_keep` function as incref/decref for it. Adds `__zipos_postdup` to fix metadata on file descriptors after dup-like operations, and adds zipos support to `sys_dup_nt` + `sys_close_nt`. * Remove noop __zipos_postdup rc is never a zipos file because it is always a previously unused file descriptor. fd is never a zipos file because that case has been handled above by __zipos_fcntl.
This commit is contained in:
parent
6556dd2673
commit
d1a745c17c
11 changed files with 138 additions and 39 deletions
|
@ -16,13 +16,30 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/createfileflags.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int __zipos_dupfd(int fd, int cmd, int start) {
|
||||
int rc;
|
||||
if (start < 0) return einval();
|
||||
if (IsWindows()) {
|
||||
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? _O_CLOEXEC : 0),
|
||||
start);
|
||||
}
|
||||
rc = sys_fcntl(fd, cmd, start, __sys_fcntl);
|
||||
if (rc != -1) {
|
||||
__zipos_postdup(fd, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int __zipos_fcntl(int fd, int cmd, uintptr_t arg) {
|
||||
if (cmd == F_GETFD) {
|
||||
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||
|
@ -38,6 +55,8 @@ int __zipos_fcntl(int fd, int cmd, uintptr_t arg) {
|
|||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
return 0;
|
||||
}
|
||||
} else if (cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC) {
|
||||
return __zipos_dupfd(fd, cmd, arg);
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
|
|
|
@ -78,7 +78,20 @@ static void *__zipos_mmap_space(size_t mapsize) {
|
|||
return start + offset;
|
||||
}
|
||||
|
||||
struct ZiposHandle *__zipos_keep(struct ZiposHandle *h) {
|
||||
atomic_fetch_add_explicit(&h->refs, 1, memory_order_relaxed);
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool __zipos_drop(struct ZiposHandle *h) {
|
||||
int refs = atomic_load_explicit(&h->refs, memory_order_acquire);
|
||||
return -1 == refs || -1 == atomic_fetch_sub(&h->refs, 1);
|
||||
}
|
||||
|
||||
void __zipos_free(struct ZiposHandle *h) {
|
||||
if (!__zipos_drop(h)) {
|
||||
return;
|
||||
}
|
||||
if (IsAsan()) {
|
||||
__asan_poison((char *)h + sizeof(struct ZiposHandle),
|
||||
h->mapsize - sizeof(struct ZiposHandle), kAsanHeapFree);
|
||||
|
@ -100,7 +113,7 @@ StartOver:
|
|||
while ((h = *ph)) {
|
||||
if (h->mapsize >= mapsize) {
|
||||
if (!_cmpxchg(ph, h, h->next)) goto StartOver;
|
||||
h->next = 0;
|
||||
atomic_init(&h->refs, 0);
|
||||
break;
|
||||
}
|
||||
ph = &h->next;
|
||||
|
@ -209,6 +222,27 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, int flags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
void __zipos_postdup(int oldfd, int newfd) {
|
||||
if (oldfd == newfd) {
|
||||
return;
|
||||
}
|
||||
if (__isfdkind(newfd, kFdZip)) {
|
||||
__zipos_free((struct ZiposHandle *)(intptr_t)g_fds.p[newfd].handle);
|
||||
if (!__isfdkind(oldfd, kFdZip)) {
|
||||
__fds_lock();
|
||||
bzero(g_fds.p + newfd, sizeof(*g_fds.p));
|
||||
__fds_unlock();
|
||||
}
|
||||
}
|
||||
if (__isfdkind(oldfd, kFdZip)) {
|
||||
__zipos_keep((struct ZiposHandle *)(intptr_t)g_fds.p[oldfd].handle);
|
||||
__fds_lock();
|
||||
__ensurefds_unlocked(newfd);
|
||||
g_fds.p[newfd] = g_fds.p[oldfd];
|
||||
__fds_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads compressed file from αcτµαlly pδrταblε εxεcµταblε object store.
|
||||
*
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
.yoink __zipos_stat
|
||||
.yoink __zipos_notat
|
||||
.yoink __zipos_mmap
|
||||
.yoink __zipos_postdup
|
||||
.yoink __zipos_keep
|
||||
.yoink __zipos_free
|
||||
|
||||
// TODO(jart): why does corruption happen when zip has no assets?
|
||||
.yoink .cosmo
|
||||
|
|
|
@ -20,8 +20,9 @@ struct ZiposHandle {
|
|||
struct Zipos *zipos;
|
||||
size_t size;
|
||||
size_t mapsize;
|
||||
size_t pos;
|
||||
size_t cfile;
|
||||
_Atomic(int) refs;
|
||||
size_t pos; // TODO atomic
|
||||
uint8_t *mem;
|
||||
uint8_t data[];
|
||||
};
|
||||
|
@ -38,6 +39,7 @@ struct Zipos {
|
|||
|
||||
int __zipos_close(int);
|
||||
void __zipos_free(struct ZiposHandle *);
|
||||
struct ZiposHandle *__zipos_keep(struct ZiposHandle *);
|
||||
struct Zipos *__zipos_get(void) pureconst;
|
||||
size_t __zipos_normpath(char *, const char *, size_t);
|
||||
ssize_t __zipos_find(struct Zipos *, struct ZiposUri *);
|
||||
|
@ -45,6 +47,7 @@ ssize_t __zipos_scan(struct Zipos *, struct ZiposUri *);
|
|||
ssize_t __zipos_parseuri(const char *, struct ZiposUri *);
|
||||
uint64_t __zipos_inode(struct Zipos *, int64_t, const void *, size_t);
|
||||
int __zipos_open(struct ZiposUri *, int);
|
||||
void __zipos_postdup(int, int);
|
||||
int __zipos_access(struct ZiposUri *, int);
|
||||
int __zipos_stat(struct ZiposUri *, struct stat *);
|
||||
int __zipos_fstat(struct ZiposHandle *, struct stat *);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue