diff options
author | dzwdz | 2024-05-11 22:05:04 +0200 |
---|---|---|
committer | dzwdz | 2024-05-11 22:05:04 +0200 |
commit | 15e02a470652a5d4ef87485b5ae12afc06dc53f8 (patch) | |
tree | e27e410885abe69d4fd20211a27e0196392993a4 /src/kernel/handleset.c | |
parent | ec3d2400db15e6911138d88f95cae141a9da2130 (diff) |
kernel: DUP_RDONLY and DUP_WRONLY
I probably should've tested DUP_WRONLY too, now that I think about it. TODO?
Diffstat (limited to 'src/kernel/handleset.c')
-rw-r--r-- | src/kernel/handleset.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/kernel/handleset.c b/src/kernel/handleset.c index a25f5c7..fc2d426 100644 --- a/src/kernel/handleset.c +++ b/src/kernel/handleset.c @@ -89,6 +89,34 @@ hs_dup(HandleSet *hs, hid_t from, hid_t to, int flags) fromh = hs_get(hs, from); if (*toh) handle_close(*toh); + + if (flags & (DUP_RDONLY | DUP_WRONLY)) { + if (!fromh || fromh->type != HANDLE_FILE) { + /* only errors out after closing the old handle */ + *toh = NULL; + return -ENOSYS; + } + + /* figure out if we need a need handle */ + bool different = false; + different = different || ((flags & DUP_RDONLY) && fromh->writeable); + different = different || ((flags & DUP_WRONLY) && fromh->readable); + + if (different) { + Handle *new = handle_init(HANDLE_FILE); + new->backend = fromh->backend; + if (new->backend) new->backend->usehcnt++; + new->file_id = fromh->file_id; + new->readable = fromh->readable && !(flags & DUP_WRONLY); + new->writeable = fromh->writeable && !(flags & DUP_RDONLY); + new->base = fromh; + fromh->refcount++; + + *toh = new; + return to; + } + } + *toh = fromh; if (fromh) fromh->refcount++; |