Mercurial > nomad
changeset 882:f9ea425467d3
objstore: implement symlink
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sun, 18 Dec 2022 10:15:13 -0500 |
parents | 180558179a08 |
children | c61456afbba3 |
files | src/objstore/CMakeLists.txt src/objstore/obj_dir_link.c src/objstore/obj_ops.c src/objstore/objstore_impl.h |
diffstat | 4 files changed, 151 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/objstore/CMakeLists.txt Sat Dec 17 20:40:39 2022 -0500 +++ b/src/objstore/CMakeLists.txt Sun Dec 18 10:15:13 2022 -0500 @@ -29,6 +29,7 @@ obj.c obj_dir.c obj_dir_create.c + obj_dir_link.c obj_dir_unlink.c obj_ops.c obj_txn.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/objstore/obj_dir_link.c Sun Dec 18 10:15:13 2022 -0500 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020,2022 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dir.h" + +#include <jeffpc/time.h> + +int dir_symlink(struct txn *txn, struct objver *dirver, const char *name, + uint32_t owner, uint32_t group, uint16_t mode, + const char *target, struct noid *_child) +{ + const uint64_t now = gettime(); + struct nattr attrs = { + .mode = mode, + .nlink = 1, + .size = strlen(target), + .atime = now, + .btime = now, + .ctime = now, + .mtime = now, + .owner = owner, + .group = group, + }; + uint8_t raw[DIR_BLOCK_SIZE]; + struct ndirent_mem ent; + bool update_existing; + struct objver *child; + uint16_t ndirents; + uint64_t diroff; + ssize_t ret; + + ASSERT(NATTR_ISLNK(mode)); + + ret = dir_lookup_entry(dirver, name, raw, &ent, &diroff, &ndirents); + if (ret) { + /* error or didn't find anything */ + if (ret != -ENOENT) + return ret; + + update_existing = false; + } else { + /* found something */ + if (!ent.all_deleted) + return -EEXIST; + + update_existing = true; + } + + /* make new oid for the child */ + child = obj_create(txn, &attrs, &dirver->obj->oid); + if (IS_ERR(child)) + return PTR_ERR(child); + + /* write out symlink target */ + ret = obj_write(txn, child, target, strlen(target), 0); + if (ret < 0) + goto err; + + if (ret != strlen(target)) { + ret = -EIO; + goto err; + } + + /* add dirent to parent dir */ + if (!update_existing) { + ret = dir_add_dirent(txn, dirver, name, mode, &child->obj->oid); + if (ret) + return ret; + } else { + ret = dir_update_dirent(txn, dirver, raw, diroff, ndirents, + name, mode, &child->obj->oid); + if (ret) + return ret; + } + + *_child = child->obj->oid; + + ret = 0; + +err: + obj_putref(child->obj); + + return ret; +}
--- a/src/objstore/obj_ops.c Sat Dec 17 20:40:39 2022 -0500 +++ b/src/objstore/obj_ops.c Sun Dec 18 10:15:13 2022 -0500 @@ -426,7 +426,50 @@ uint32_t owner, uint32_t group, uint16_t mode, const char *target, struct noid *child) { - return -ENOTSUP; + struct objver *newver; + struct obj *dir; + struct txn txn; + int ret; + + if (!diropen || !name || !target) + return -EINVAL; + + /* must have a type */ + if (!NATTR_ISLNK(mode)) + return -EINVAL; + + dir = diropen->obj; + + if (diropen->qualified) + return -EROFS; + + MXLOCK(&dir->lock); + + if (!NATTR_ISDIR(diropen->ver->attrs.mode)) { + ret = -ENOTDIR; + goto err; + } + + ret = txn_begin(&txn, diropen->ver->obj->clone); + if (ret) + goto err; + + newver = obj_cow(&txn, diropen); + if (IS_ERR(newver)) { + ret = PTR_ERR(newver); + goto err_txn; + } + + ret = dir_symlink(&txn, newver, name, owner, group, mode, target, child); + +err_txn: + ret = txn_commitabort(&txn, ret); + newver = NULL; /* prevent accidental use */ + +err: + MXUNLOCK(&dir->lock); + + return ret; } int objstore_link(struct objstore_open_obj_info *diropen, const char *name,
--- a/src/objstore/objstore_impl.h Sat Dec 17 20:40:39 2022 -0500 +++ b/src/objstore/objstore_impl.h Sun Dec 18 10:15:13 2022 -0500 @@ -105,6 +105,9 @@ extern int dir_create(struct txn *txn, struct objver *dirver, const char *name, uint32_t owner, uint32_t group, uint16_t mode, struct noid *child); +extern int dir_symlink(struct txn *txn, struct objver *dirver, const char *name, + uint32_t owner, uint32_t group, uint16_t mode, + const char *target, struct noid *_child); extern int dir_unlink(struct txn *txn, struct objver *dirver, const char *name, const struct noid *desired, bool rmdir);