Mercurial > nomad
changeset 536:752203924c31
objstore/posix: implement getdent obj op
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Tue, 23 Oct 2018 01:54:01 +0200 |
parents | 129b89b9e4ae |
children | 45eb64a614ca |
files | src/objstore/posix/obj.c |
diffstat | 1 files changed, 79 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/objstore/posix/obj.c Tue Oct 23 01:53:39 2018 +0200 +++ b/src/objstore/posix/obj.c Tue Oct 23 01:54:01 2018 +0200 @@ -328,6 +328,84 @@ return ret; } +static int posix_getdent(struct objver *dirver, const uint64_t offset, + struct ndirent *child) +{ + struct posix_dirent *dirent; + struct posix_ver_header hdr; + size_t off; + char *name; + void *buf; + int ret; + int fd; + + fd = open_ver(dirver); + if (fd < 0) + return fd; + + ret = read_ver_header(dirver, fd, &hdr); + if (ret) + goto err; + + /* generic code already checks for this */ + ASSERT(NATTR_ISDIR(hdr.mode)); + + if (offset >= hdr.size) { + ret = -ENOENT; + goto err; + } + + buf = xmmap(NULL, hdr.size, PROT_READ, MAP_SHARED, fd, + sizeof(struct posix_ver_header)); + if (IS_ERR(buf)) { + ret = PTR_ERR(buf); + goto err; + } + + /* seek (safely) to the correct place */ + for (dirent = buf, off = 0; + (off < hdr.size) && (off < offset); + dirent = buf + off, + off += sizeof(struct posix_dirent) + dirent->namelen) + ; + + /* must match the offset exactly */ + if (off != offset) { + ret = -ENOENT; + goto err_unmap; + } + + name = malloc(dirent->namelen + 1); + if (name) { + child->entry_size = sizeof(struct posix_dirent) + dirent->namelen; + child->name = name; + child->namelen = dirent->namelen; + child->type = dirent->type; + + if (dirent->type == NDIRENT_TYPE_GRAFT) + noid_set(&child->oid, &dirent->tgt.graft, 0, 0); + else + noid_set(&child->oid, &dirver->obj->vol->id, + be32_to_cpu(dirent->tgt.host), + be32_to_cpu(dirent->tgt.uniq)); + + memcpy(name, dirent->name, dirent->namelen); + name[dirent->namelen] = '\0'; + + ret = 0; + } else { + ret = -ENOMEM; + } + +err_unmap: + xmunmap(buf, hdr.size); + +err: + xclose(fd); + + return ret; +} + static void posix_free(struct obj *obj) { struct posix_obj *pobj = obj->private; @@ -339,5 +417,6 @@ .getversion = posix_getversion, .getattr = posix_getattr, .lookup_one = posix_lookup_one, + .getdent = posix_getdent, .free = posix_free, };