Commit 1c7e24f1803c43083e220e0e36c22555e478551d

Stefan Sperling 2018-04-02T10:05:35

avoid unnecessary string copies and allocations in get_packfile_size()

diff --git a/lib/pack.c b/lib/pack.c
index 10e8be9..392de87 100644
--- a/lib/pack.c
+++ b/lib/pack.c
@@ -74,29 +74,41 @@ verify_fanout_table(uint32_t *fanout_table)
 }
 
 static const struct got_error *
-get_packfile_size(size_t *size, const char *path_idx)
+get_packfile_size(size_t *size, const char *path)
 {
 	struct stat sb;
-	char *path_pack;
-	char base_path[PATH_MAX];
 	char *dot;
 
-	if (strlcpy(base_path, path_idx, PATH_MAX) > PATH_MAX)
-		return got_error(GOT_ERR_NO_SPACE);
-
-	dot = strrchr(base_path, '.');
+	dot = strrchr(path, '.');
 	if (dot == NULL)
 		return got_error(GOT_ERR_BAD_PATH);
-	*dot = '\0';
-	if (asprintf(&path_pack, "%s.pack", base_path) == -1)
-		return got_error_from_errno();
 
-	if (stat(path_pack, &sb) != 0) {
+	/* Path must point to a pack index or to a pack file. */
+	if (strcmp(dot, ".idx") == 0) {
+		char *path_pack;
+		char base_path[PATH_MAX];
+
+		/* Convert pack index path to pack file path. */
+		if (strlcpy(base_path, path, PATH_MAX) > PATH_MAX)
+			return got_error(GOT_ERR_NO_SPACE);
+		dot = strrchr(base_path, '.');
+		if (dot == NULL)
+			return got_error(GOT_ERR_BAD_PATH);
+		*dot = '\0';
+		if (asprintf(&path_pack, "%s.pack", base_path) == -1)
+			return got_error_from_errno();
+
+		if (stat(path_pack, &sb) != 0) {
+			free(path_pack);
+			return got_error_from_errno();
+		}
 		free(path_pack);
-		return got_error_from_errno();
-	}
+	} else if (strcmp(dot, ".pack") == 0) {
+		if (stat(path, &sb) != 0)
+			return got_error_from_errno();
+	} else
+		return got_error(GOT_ERR_BAD_PATH);
 
-	free(path_pack);
 	*size = sb.st_size;
 	return 0;
 }