[PATCH v2 06/22] cache.c: don't use statically sized buffers for filenames

John Keeping john at keeping.me.uk
Sun Apr 7 16:26:35 CEST 2013


Instead use "struct strbuf" from Git to remove the limit on file path
length.

Signed-off-by: John Keeping <john at keeping.me.uk>
---
Changes since v1:
- Reset the buffer length before appending each filename to the base
  path.

 cache.c | 57 ++++++++++++++++++++-------------------------------------
 1 file changed, 20 insertions(+), 37 deletions(-)

diff --git a/cache.c b/cache.c
index 3127fc2..c1d777b 100644
--- a/cache.c
+++ b/cache.c
@@ -312,9 +312,9 @@ int cache_process(int size, const char *path, const char *key, int ttl,
 		  cache_fill_fn fn, void *cbdata)
 {
 	unsigned long hash;
-	int len, i;
-	char filename[1024];
-	char lockname[1024 + 5];  /* 5 = ".lock" */
+	int i;
+	struct strbuf filename = STRBUF_INIT;
+	struct strbuf lockname = STRBUF_INIT;
 	struct cache_slot slot;
 
 	/* If the cache is disabled, just generate the content */
@@ -329,32 +329,22 @@ int cache_process(int size, const char *path, const char *key, int ttl,
 		fn(cbdata);
 		return 0;
 	}
-	len = strlen(path);
-	if (len > sizeof(filename) - 10) { /* 10 = "/01234567\0" */
-		cache_log("[cgit] Cache path too long, caching is disabled: %s\n",
-			  path);
-		fn(cbdata);
-		return 0;
-	}
 	if (!key)
 		key = "";
 	hash = hash_str(key) % size;
-	strcpy(filename, path);
-	if (filename[len - 1] != '/')
-		filename[len++] = '/';
+	strbuf_addstr(&filename, path);
+	strbuf_ensure_end(&filename, '/');
 	for (i = 0; i < 8; i++) {
-		sprintf(filename + len++, "%x",
-			(unsigned char)(hash & 0xf));
+		strbuf_addf(&filename, "%x", (unsigned char)(hash & 0xf));
 		hash >>= 4;
 	}
-	filename[len] = '\0';
-	strcpy(lockname, filename);
-	strcpy(lockname + len, ".lock");
+	strbuf_addbuf(&lockname, &filename);
+	strbuf_addstr(&lockname, ".lock");
 	slot.fn = fn;
 	slot.cbdata = cbdata;
 	slot.ttl = ttl;
-	slot.cache_name = filename;
-	slot.lock_name = lockname;
+	slot.cache_name = strbuf_detach(&filename, NULL);
+	slot.lock_name = strbuf_detach(&lockname, NULL);
 	slot.key = key;
 	slot.keylen = strlen(key);
 	return process_slot(&slot);
@@ -381,18 +371,13 @@ int cache_ls(const char *path)
 	struct dirent *ent;
 	int err = 0;
 	struct cache_slot slot;
-	char fullname[1024];
-	char *name;
+	struct strbuf fullname = STRBUF_INIT;
+	size_t prefixlen;
 
 	if (!path) {
 		cache_log("[cgit] cache path not specified\n");
 		return -1;
 	}
-	if (strlen(path) > 1024 - 10) {
-		cache_log("[cgit] cache path too long: %s\n",
-			  path);
-		return -1;
-	}
 	dir = opendir(path);
 	if (!dir) {
 		err = errno;
@@ -400,30 +385,28 @@ int cache_ls(const char *path)
 			  path, strerror(err), err);
 		return err;
 	}
-	strcpy(fullname, path);
-	name = fullname + strlen(path);
-	if (*(name - 1) != '/') {
-		*name++ = '/';
-		*name = '\0';
-	}
-	slot.cache_name = fullname;
+	strbuf_addstr(&fullname, path);
+	strbuf_ensure_end(&fullname, '/');
+	prefixlen = fullname.len;
 	while ((ent = readdir(dir)) != NULL) {
 		if (strlen(ent->d_name) != 8)
 			continue;
-		strcpy(name, ent->d_name);
+		strbuf_setlen(&fullname, prefixlen);
+		strbuf_addstr(&fullname, ent->d_name);
 		if ((err = open_slot(&slot)) != 0) {
 			cache_log("[cgit] unable to open path %s: %s (%d)\n",
-				  fullname, strerror(err), err);
+				  fullname.buf, strerror(err), err);
 			continue;
 		}
 		printf("%s %s %10"PRIuMAX" %s\n",
-		       name,
+		       fullname.buf,
 		       sprintftime("%Y-%m-%d %H:%M:%S",
 				   slot.cache_st.st_mtime),
 		       (uintmax_t)slot.cache_st.st_size,
 		       slot.buf);
 		close_slot(&slot);
 	}
+	slot.cache_name = strbuf_detach(&fullname, NULL);
 	closedir(dir);
 	return 0;
 }
-- 
1.8.2.692.g17a9715





More information about the CGit mailing list