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:
Jōshin 2023-12-01 03:08:30 -05:00 committed by GitHub
parent 6556dd2673
commit d1a745c17c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 138 additions and 39 deletions

View file

@ -59,30 +59,34 @@ static textwindows int sys_dup_nt_impl(int oldfd, int newfd, int flags,
return -1;
}
if (g_fds.p[newfd].kind) {
if (g_fds.p[newfd].kind == kFdZip) {
_weaken(__zipos_close)(newfd);
} else {
sys_close_nt(newfd, newfd);
}
sys_close_nt(newfd, newfd);
}
}
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &handle, 0, true,
kNtDuplicateSameAccess)) {
g_fds.p[newfd] = g_fds.p[oldfd];
g_fds.p[newfd].handle = handle;
if (flags & _O_CLOEXEC) {
g_fds.p[newfd].flags |= _O_CLOEXEC;
} else {
g_fds.p[newfd].flags &= ~_O_CLOEXEC;
}
if (__isfdkind(oldfd, kFdZip)) {
handle = (intptr_t)_weaken(__zipos_keep)(
(struct ZiposHandle *)(intptr_t)g_fds.p[oldfd].handle);
rc = newfd;
} else {
__releasefd(newfd);
rc = __winerr();
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &handle, 0, true,
kNtDuplicateSameAccess)) {
rc = newfd;
} else {
rc = __winerr();
__releasefd(newfd);
__fds_unlock();
return rc;
}
}
g_fds.p[newfd] = g_fds.p[oldfd];
g_fds.p[newfd].handle = handle;
if (flags & _O_CLOEXEC) {
g_fds.p[newfd].flags |= _O_CLOEXEC;
} else {
g_fds.p[newfd].flags &= ~_O_CLOEXEC;
}
__fds_unlock();
return rc;
}