changeset 782:76ebc6370b47

objstore: check for name duplicates in dirblock_add_dirent It would be very bad if we ended up with two entries for the same name. Note that this doesn't ensure that we don't end up with more than one entry for a name in different blocks. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Tue, 31 Mar 2020 11:56:02 -0400
parents ca83139c8103
children 4a1b39092b2f
files src/objstore/dirblock.c
diffstat 1 files changed, 26 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/objstore/dirblock.c	Tue Mar 31 11:09:07 2020 -0400
+++ b/src/objstore/dirblock.c	Tue Mar 31 11:56:02 2020 -0400
@@ -143,6 +143,24 @@
 	return buffer_truncate(buf, DIR_BLOCK_SIZE);
 }
 
+static ssize_t __find_dirent(struct dirblock *block, const char *name)
+{
+	const size_t namelen = strlen(name);
+	size_t i;
+
+	for (i = 0; i < block->ndirents; i++) {
+		if (namelen != block->entries[i].dirent.namelen)
+			continue;
+
+		if (strncmp(name, block->entries[i].name, namelen))
+			continue;
+
+		return i;
+	}
+
+	return -ENOENT;
+}
+
 int dirblock_add_dirent(struct dirblock *block, const char *name,
 			const struct ndirent_tgt *tgt)
 {
@@ -150,12 +168,18 @@
 	uint8_t tgtrawbuf[128];
 	struct buffer tgtbuf;
 	size_t space_needed;
-	int idx;
-	int ret;
+	ssize_t ret;
+	size_t idx;
 
 	if (namelen > MAX_NAME_LEN)
 		return -ENAMETOOLONG;
 
+	ret = __find_dirent(block, name);
+	if (ret >= 0)
+		return -EEXIST;
+	if (ret != -ENOENT)
+		return ret;
+
 	buffer_init_static(&tgtbuf, tgtrawbuf, sizeof(tgtrawbuf), true);
 	VERIFY0(buffer_truncate(&tgtbuf, 0));