Commit b29656e27eca86259a4fc9099e9b5b31433e0065

Stefan Sperling 2018-03-16T23:05:12

set obj->size of packed deltified objects to object's actual size

diff --git a/lib/delta.c b/lib/delta.c
index 94fda1c..f28e5f7 100644
--- a/lib/delta.c
+++ b/lib/delta.c
@@ -315,16 +315,18 @@ got_delta_apply_in_mem(uint8_t *base_buf, const uint8_t *delta_buf,
 
 const struct got_error *
 got_delta_apply(FILE *base_file, const uint8_t *delta_buf,
-    size_t delta_len, FILE *outfile)
+    size_t delta_len, FILE *outfile, size_t *outsize)
 {
 	const struct got_error *err = NULL;
 	uint64_t base_size, result_size;
-	size_t remain, outsize = 0;
+	size_t remain = 0;
 	const uint8_t *p;
 	FILE *memstream = NULL;
 	char *memstream_buf = NULL;
 	size_t memstream_size = 0;
 
+	*outsize = 0;
+
 	if (delta_len < GOT_DELTA_STREAM_LENGTH_MIN)
 		return got_error(GOT_ERR_BAD_DELTA);
 
@@ -349,7 +351,7 @@ got_delta_apply(FILE *base_file, const uint8_t *delta_buf,
 			err = copy_from_base(base_file, offset, len,
 			    memstream ? memstream : outfile);
 			if (err == NULL) {
-				outsize += len;
+				*outsize += len;
 				if (remain > 0) {
 					p++;
 					remain--;
@@ -367,11 +369,11 @@ got_delta_apply(FILE *base_file, const uint8_t *delta_buf,
 			err = copy_from_delta(&p, &remain, len,
 			    memstream ? memstream : outfile);
 			if (err == NULL)
-				outsize += len;
+				*outsize += len;
 		}
 	}
 
-	if (outsize != result_size)
+	if (*outsize != result_size)
 		err = got_error(GOT_ERR_BAD_DELTA);
 
 	if (memstream != NULL) {
diff --git a/lib/got_delta_lib.h b/lib/got_delta_lib.h
index 2d360ff..e1098e1 100644
--- a/lib/got_delta_lib.h
+++ b/lib/got_delta_lib.h
@@ -38,7 +38,7 @@ const struct got_error *got_delta_get_sizes(uint64_t *, uint64_t *,
 const struct got_error *got_delta_apply_in_mem(uint8_t *, const uint8_t *,
     size_t, uint8_t *, size_t *);
 const struct got_error *got_delta_apply(FILE *, const uint8_t *, size_t,
-    FILE *);
+    FILE *, size_t *);
 
 /*
  * The amount of result data we may keep in RAM while applying deltas.
diff --git a/lib/object.c b/lib/object.c
index 8a150ed..40fa201 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -625,8 +625,8 @@ got_object_commit_open(struct got_commit_object **commit,
 		err = got_packfile_extract_object_to_mem(&buf, &len, obj, repo);
 		if (err)
 			return err;
-		len -= obj->hdrlen;
-		err = parse_commit_object(commit, buf + obj->hdrlen, len);
+		obj->size = len;
+		err = parse_commit_object(commit, buf, len);
 		free(buf);
 	} else {
 		FILE *f;
@@ -701,8 +701,8 @@ got_object_tree_open(struct got_tree_object **tree,
 		err = got_packfile_extract_object_to_mem(&buf, &len, obj, repo);
 		if (err)
 			return err;
-		len -= obj->hdrlen;
-		err = parse_tree_object(tree, repo, buf + obj->hdrlen, len);
+		obj->size = len;
+		err = parse_tree_object(tree, repo, buf, len);
 		free(buf);
 	} else {
 		FILE *f;
diff --git a/lib/pack.c b/lib/pack.c
index a8cbf63..b9e653b 100644
--- a/lib/pack.c
+++ b/lib/pack.c
@@ -1082,17 +1082,20 @@ get_cached_delta(uint8_t **delta_buf, size_t *delta_len,
 }
 
 static const struct got_error *
-dump_delta_chain_to_file(struct got_delta_chain *deltas, FILE *outfile,
-    FILE *packfile, const char *path_packfile, struct got_repository *repo)
+dump_delta_chain_to_file(size_t *result_size, struct got_delta_chain *deltas,
+    FILE *outfile, FILE *packfile, const char *path_packfile,
+    struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
 	struct got_delta *delta;
 	FILE *base_file = NULL, *accum_file = NULL;
 	uint8_t *base_buf = NULL, *accum_buf = NULL;
-	size_t accum_size;
+	size_t accum_size = 0;
 	uint64_t max_size;
 	int n = 0;
 
+	*result_size = 0;
+
 	if (SIMPLEQ_EMPTY(&deltas->entries))
 		return got_error(GOT_ERR_BAD_DELTA_CHAIN);
 
@@ -1192,7 +1195,8 @@ dump_delta_chain_to_file(struct got_delta_chain *deltas, FILE *outfile,
 		} else {
 			err = got_delta_apply(base_file, delta_buf, delta_len,
 			    /* Final delta application writes to output file. */
-			    ++n < deltas->nentries ? accum_file : outfile);
+			    ++n < deltas->nentries ? accum_file : outfile,
+			    &accum_size);
 		}
 		if (err)
 			goto done;
@@ -1226,6 +1230,8 @@ done:
 	if (accum_file)
 		fclose(accum_file);
 	rewind(outfile);
+	if (err == NULL)
+		*result_size = accum_size;
 	return err;
 }
 
@@ -1372,8 +1378,8 @@ got_packfile_extract_object(FILE **f, struct got_object *obj,
 
 		err = got_inflate_to_file(&obj->size, packfile, *f);
 	} else
-		err = dump_delta_chain_to_file(&obj->deltas, *f, packfile,
-		    obj->path_packfile, repo);
+		err = dump_delta_chain_to_file(&obj->size, &obj->deltas, *f,
+		    packfile, obj->path_packfile, repo);
 done:
 	if (packfile)
 		fclose(packfile);
diff --git a/regress/delta/delta_test.c b/regress/delta/delta_test.c
index 1567c43..1486b9c 100644
--- a/regress/delta/delta_test.c
+++ b/regress/delta/delta_test.c
@@ -77,11 +77,15 @@ delta_apply()
 		rewind(base_file);
 
 		err = got_delta_apply(base_file, dt->delta, dt->delta_len,
-		    result_file);
+		    result_file, &len);
 		fclose(base_file);
 		if (err)
 			break;
 		result_len = strlen(dt->expected);
+		if (result_len != len) {
+			err = got_ferror(result_file, GOT_ERR_BAD_DELTA);
+			break;
+		}
 		n = fread(buf, result_len, 1, result_file);
 		if (n != 1 || strncmp(buf, dt->expected, result_len) != 0) {
 			err = got_ferror(result_file, GOT_ERR_BAD_DELTA);