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,
 };