Commit Diff


commit - ec2b23c5d2570888a1d83ce2e8eee5a90eeff695
commit + f4ae6ddb59a1edbd016ad7f0e27c2599f8966e19
blob - 3d3f817d6a45800bef116a8942a2a06a9a32aa14
blob + 34ab6c7e364259d06257ce50a763bb09dfacd8cf
--- got/got.c
+++ got/got.c
@@ -3547,9 +3547,20 @@ diff_blobs(struct got_object_id *blob_id1, struct got_
 	const struct got_error *err = NULL;
 	struct got_blob_object *blob1 = NULL, *blob2 = NULL;
 	FILE *f1 = NULL, *f2 = NULL;
+	int fd1 = -1, fd2 = -1;
+
+	fd1 = got_opentempfd();
+	if (fd1 == -1)
+		return got_error_from_errno("got_opentempfd");
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 
 	if (blob_id1) {
-		err = got_object_open_as_blob(&blob1, repo, blob_id1, 8192);
+		err = got_object_open_as_blob(&blob1, repo, blob_id1, 8192,
+		    fd1);
 		if (err)
 			goto done;
 		f1 = got_opentemp();
@@ -3559,7 +3570,7 @@ diff_blobs(struct got_object_id *blob_id1, struct got_
 		}
 	}
 
-	err = got_object_open_as_blob(&blob2, repo, blob_id2, 8192);
+	err = got_object_open_as_blob(&blob2, repo, blob_id2, 8192, fd2);
 	if (err)
 		goto done;
 
@@ -3574,8 +3585,12 @@ diff_blobs(struct got_object_id *blob_id1, struct got_
 	err = got_diff_blob(NULL, NULL, blob1, blob2, f1, f2, path, path,
 	    diff_context, ignore_whitespace, force_text_diff, outfile);
 done:
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob1)
 		got_object_blob_close(blob1);
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	got_object_blob_close(blob2);
 	if (f1 && fclose(f1) == EOF && err == NULL)
 		err = got_error_from_errno("fclose");
@@ -4618,7 +4633,7 @@ print_diff(void *arg, unsigned char status, unsigned c
 	struct print_diff_arg *a = arg;
 	const struct got_error *err = NULL;
 	struct got_blob_object *blob1 = NULL;
-	int fd = -1;
+	int fd = -1, fd1 = -1;
 	FILE *f1 = NULL, *f2 = NULL;
 	char *abspath = NULL, *label1 = NULL;
 	struct stat sb;
@@ -4683,11 +4698,17 @@ print_diff(void *arg, unsigned char status, unsigned c
 		goto done;
 	}
 
+	fd1 = got_opentempfd();
+	if (fd1 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
 	if (staged_status == GOT_STATUS_ADD ||
 	    staged_status == GOT_STATUS_MODIFY) {
 		char *id_str;
 		err = got_object_open_as_blob(&blob1, a->repo, staged_blob_id,
-		    8192);
+		    8192, fd1);
 		if (err)
 			goto done;
 		err = got_object_id_str(&id_str, staged_blob_id);
@@ -4700,7 +4721,8 @@ print_diff(void *arg, unsigned char status, unsigned c
 		}
 		free(id_str);
 	} else if (status != GOT_STATUS_ADD) {
-		err = got_object_open_as_blob(&blob1, a->repo, blob_id, 8192);
+		err = got_object_open_as_blob(&blob1, a->repo, blob_id, 8192,
+		    fd1);
 		if (err)
 			goto done;
 	}
@@ -4716,7 +4738,7 @@ print_diff(void *arg, unsigned char status, unsigned c
 			fd = openat(dirfd, de_name,
 			    O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
 			if (fd == -1) {
-				if (!got_err_open_nofollow_on_symlink()) { 
+				if (!got_err_open_nofollow_on_symlink()) {
 					err = got_error_from_errno2("openat",
 					    abspath);
 					goto done;
@@ -4763,12 +4785,14 @@ print_diff(void *arg, unsigned char status, unsigned c
 		    blob1);
 		if (err)
 			goto done;
-	}	
+	}
 
 	err = got_diff_blob_file(blob1, f1, size1, label1, f2, sb.st_size,
 	    path, a->diff_context, a->ignore_whitespace, a->force_text_diff,
 	    stdout);
 done:
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob1)
 		got_object_blob_close(blob1);
 	if (f1 && fclose(f1) == EOF && err == NULL)
@@ -5291,9 +5315,13 @@ cmd_blame(int argc, char *argv[])
 	struct got_blob_object *blob = NULL;
 	char *commit_id_str = NULL;
 	struct blame_cb_args bca;
-	int ch, obj_type, i;
+	int ch, obj_type, i, fd = -1;
 	off_t filesize;
 	int *pack_fds = NULL;
+
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
 
 	memset(&bca, 0, sizeof(bca));
 
@@ -5445,7 +5473,7 @@ cmd_blame(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_object_open_as_blob(&blob, repo, obj_id, 8192);
+	error = got_object_open_as_blob(&blob, repo, obj_id, 8192, fd);
 	if (error)
 		goto done;
 	bca.f = got_opentemp();
@@ -5487,6 +5515,8 @@ done:
 	free(obj_id);
 	if (commit)
 		got_object_commit_close(commit);
+	if (fd != -1 && close(fd) == -1 && error == NULL)
+		error = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	if (worktree)
@@ -12228,13 +12258,22 @@ cat_blob(struct got_object_id *id, struct got_reposito
 {
 	const struct got_error *err;
 	struct got_blob_object *blob;
+	int fd = -1;
+
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
 
-	err = got_object_open_as_blob(&blob, repo, id, 8192);
+	err = got_object_open_as_blob(&blob, repo, id, 8192, fd);
 	if (err)
-		return err;
+		goto done;
 
 	err = got_object_blob_dump_to_file(NULL, NULL, NULL, outfile, blob);
-	got_object_blob_close(blob);
+done:
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
+	if (blob)
+		got_object_blob_close(blob);
 	return err;
 }
 
blob - 82a511cd01114ad856ae35699580cea0aad840cc
blob + 613f534afc172336d81db615fa60e942b4f1734f
--- gotweb/gotweb.c
+++ gotweb/gotweb.c
@@ -4063,8 +4063,12 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct
 	struct got_blob_object *blob = NULL;
 	char *path = NULL, *in_repo_path = NULL;
 	struct gw_blame_cb_args bca;
-	int i, obj_type;
+	int i, obj_type, fd = -1;
 	off_t filesize;
+
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
 
 	memset(&bca, 0, sizeof(bca));
 
@@ -4108,7 +4112,8 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct
 		goto done;
 	}
 
-	error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192);
+	error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192,
+	    fd);
 	if (error)
 		goto done;
 
@@ -4149,6 +4154,8 @@ done:
 	free(obj_id);
 	free(path);
 
+	if (fd != -1 && close(fd) == -1 && error == NULL)
+		error = got_error_from_errno("close");
 	if (blob) {
 		free(bca.line_offsets);
 		for (i = 0; i < bca.nlines; i++) {
@@ -4176,11 +4183,15 @@ gw_output_blob_buf(struct gw_trans *gw_trans, struct g
 	struct got_commit_object *commit = NULL;
 	struct got_blob_object *blob = NULL;
 	char *path = NULL, *in_repo_path = NULL;
-	int obj_type, set_mime = 0;
+	int obj_type, set_mime = 0, fd = -1;
 	size_t len, hdrlen;
 	const uint8_t *buf;
 	enum kcgi_err kerr = KCGI_OK;
 
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
+
 	if (asprintf(&path, "%s%s%s",
 	    gw_trans->repo_folder ? gw_trans->repo_folder : "",
 	    gw_trans->repo_folder ? "/" : "",
@@ -4221,7 +4232,8 @@ gw_output_blob_buf(struct gw_trans *gw_trans, struct g
 		goto done;
 	}
 
-	error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192);
+	error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192,
+	    fd);
 	if (error)
 		goto done;
 
@@ -4257,6 +4269,8 @@ done:
 	free(commit_id);
 	free(obj_id);
 	free(path);
+	if (fd != -1 && close(fd) == -1 && error == NULL)
+		error = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	if (commit)
blob - 0a162cbd301d5069ad3612113a16489ad4b7fd87
blob + a8d0318ceaa7152627e8c8718ba039f8517bc3e4
--- include/got_object.h
+++ include/got_object.h
@@ -260,7 +260,7 @@ const struct got_error *got_object_tree_path_changed(i
  * The caller must dispose of the blob with got_object_blob_close().
  */
 const struct got_error *got_object_open_as_blob(struct got_blob_object **,
-    struct got_repository *, struct got_object_id *, size_t);
+    struct got_repository *, struct got_object_id *, size_t, int);
 
 /* Dispose of a blob object. */
 const struct got_error *got_object_blob_close(struct got_blob_object *);
blob - f0716a472395e1397b1ded375713011c41784382
blob + c95dcf7b940e7c0d35bb98e78c05847c04390c98
--- lib/blame.c
+++ lib/blame.c
@@ -203,6 +203,7 @@ blame_commit(struct got_blame *blame, struct got_objec
 	struct got_object_id *pblob_id = NULL;
 	struct got_blob_object *pblob = NULL;
 	struct diff_result *diff_result = NULL;
+	int fd = -1;
 
 	err = got_object_open_as_commit(&commit, repo, id);
 	if (err)
@@ -214,6 +215,12 @@ blame_commit(struct got_blame *blame, struct got_objec
 		return NULL;
 	}
 
+	fd = got_opentempfd();
+	if (fd == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
 	err = got_object_open_as_commit(&pcommit, repo, &pid->id);
 	if (err)
 		goto done;
@@ -225,7 +232,7 @@ blame_commit(struct got_blame *blame, struct got_objec
 		goto done;
 	}
 
-	err = got_object_open_as_blob(&pblob, repo, pblob_id, 8192);
+	err = got_object_open_as_blob(&pblob, repo, pblob_id, 8192, fd);
 	if (err)
 		goto done;
 
@@ -272,6 +279,8 @@ done:
 	if (pcommit)
 		got_object_commit_close(pcommit);
 	free(pblob_id);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (pblob)
 		got_object_blob_close(pblob);
 	return err;
@@ -506,9 +515,13 @@ blame_open(struct got_blame **blamep, const char *path
 	struct got_blob_object *blob = NULL;
 	struct got_blame *blame = NULL;
 	struct got_object_id *id = NULL;
-	int lineno;
+	int lineno, fd = -1;
 	struct got_commit_graph *graph = NULL;
 
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
+
 	*blamep = NULL;
 
 	err = got_object_open_as_commit(&start_commit, repo, start_commit_id);
@@ -519,7 +532,7 @@ blame_open(struct got_blame **blamep, const char *path
 	if (err)
 		goto done;
 
-	err = got_object_open_as_blob(&blob, repo, obj_id, 8192);
+	err = got_object_open_as_blob(&blob, repo, obj_id, 8192, fd);
 	if (err)
 		goto done;
 
@@ -631,6 +644,8 @@ done:
 	if (graph)
 		got_commit_graph_close(graph);
 	free(obj_id);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	if (start_commit)
blob - fea8300f838a573db96d58e41398f9efda236a06
blob + 557e270b857670c84be05428548bc1ccf36e6ebb
--- lib/diff.c
+++ lib/diff.c
@@ -280,18 +280,27 @@ diff_added_blob(struct got_object_id *id, FILE *f, con
 	const struct got_error *err;
 	struct got_blob_object  *blob = NULL;
 	struct got_object *obj = NULL;
+	int fd = -1;
 
 	err = got_object_open(&obj, repo, id);
 	if (err)
 		return err;
 
-	err = got_object_blob_open(&blob, repo, obj, 8192);
+	fd = got_opentempfd();
+	if (fd == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
+	err = got_object_blob_open(&blob, repo, obj, 8192, fd);
 	if (err)
 		goto done;
 	err = cb(cb_arg, NULL, blob, NULL, f, NULL, id,
 	    NULL, label, 0, mode, repo);
 done:
 	got_object_close(obj);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	return err;
@@ -308,10 +317,23 @@ diff_modified_blob(struct got_object_id *id1, struct g
 	struct got_object *obj2 = NULL;
 	struct got_blob_object *blob1 = NULL;
 	struct got_blob_object *blob2 = NULL;
+	int fd1 = -1, fd2 = -1;
 
 	err = got_object_open(&obj1, repo, id1);
 	if (err)
 		return err;
+
+	fd1 = got_opentempfd();
+	if (fd1 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
 	if (obj1->type != GOT_OBJ_TYPE_BLOB) {
 		err = got_error(GOT_ERR_OBJ_TYPE);
 		goto done;
@@ -325,11 +347,11 @@ diff_modified_blob(struct got_object_id *id1, struct g
 		goto done;
 	}
 
-	err = got_object_blob_open(&blob1, repo, obj1, 8192);
+	err = got_object_blob_open(&blob1, repo, obj1, 8192, fd1);
 	if (err)
 		goto done;
 
-	err = got_object_blob_open(&blob2, repo, obj2, 8192);
+	err = got_object_blob_open(&blob2, repo, obj2, 8192, fd2);
 	if (err)
 		goto done;
 
@@ -340,8 +362,12 @@ done:
 		got_object_close(obj1);
 	if (obj2)
 		got_object_close(obj2);
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob1)
 		got_object_blob_close(blob1);
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob2)
 		got_object_blob_close(blob2);
 	return err;
@@ -354,18 +380,25 @@ diff_deleted_blob(struct got_object_id *id, FILE *f, c
 	const struct got_error *err;
 	struct got_blob_object  *blob = NULL;
 	struct got_object *obj = NULL;
+	int fd = -1;
 
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
+
 	err = got_object_open(&obj, repo, id);
 	if (err)
 		return err;
 
-	err = got_object_blob_open(&blob, repo, obj, 8192);
+	err = got_object_blob_open(&blob, repo, obj, 8192, fd);
 	if (err)
 		goto done;
 	err = cb(cb_arg, blob, NULL, f, NULL, id, NULL, label, NULL,
 	    mode, 0, repo);
 done:
 	got_object_close(obj);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	return err;
@@ -723,17 +756,27 @@ got_diff_objects_as_blobs(off_t **line_offsets, size_t
 {
 	const struct got_error *err;
 	struct got_blob_object *blob1 = NULL, *blob2 = NULL;
+	int fd1 = -1, fd2 = -1;
 
 	if (id1 == NULL && id2 == NULL)
 		return got_error(GOT_ERR_NO_OBJ);
+
+	fd1 = got_opentempfd();
+	if (fd1 == -1)
+		return got_error_from_errno("got_opentempfd");
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 
 	if (id1) {
-		err = got_object_open_as_blob(&blob1, repo, id1, 8192);
+		err = got_object_open_as_blob(&blob1, repo, id1, 8192, fd1);
 		if (err)
 			goto done;
 	}
 	if (id2) {
-		err = got_object_open_as_blob(&blob2, repo, id2, 8192);
+		err = got_object_open_as_blob(&blob2, repo, id2, 8192, fd2);
 		if (err)
 			goto done;
 	}
@@ -741,8 +784,12 @@ got_diff_objects_as_blobs(off_t **line_offsets, size_t
 	    label1, label2, diff_context, ignore_whitespace, force_text_diff,
 	    outfile);
 done:
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob1)
 		got_object_blob_close(blob1);
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob2)
 		got_object_blob_close(blob2);
 	return err;
@@ -758,7 +805,16 @@ diff_paths(struct got_tree_object *tree1, struct got_t
 	struct got_object_id *id1 = NULL, *id2 = NULL;
 	struct got_tree_object *subtree1 = NULL, *subtree2 = NULL;
 	struct got_blob_object *blob1 = NULL, *blob2 = NULL;
+	int fd1 = -1, fd2 = -1;
 
+	fd1 = got_opentempfd();
+	if (fd1 == -1)
+		return got_error_from_errno("got_opentempfd");
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 	TAILQ_FOREACH(pe, paths, entry) {
 		int type1 = GOT_OBJ_TYPE_ANY, type2 = GOT_OBJ_TYPE_ANY;
 		mode_t mode1 = 0, mode2 = 0;
@@ -820,13 +876,13 @@ diff_paths(struct got_tree_object *tree1, struct got_t
 		    type2 == GOT_OBJ_TYPE_BLOB) {
 			if (id1) {
 				err = got_object_open_as_blob(&blob1, repo,
-				    id1, 8192);
+				    id1, 8192, fd1);
 				if (err)
 					goto done;
 			}
 			if (id2) {
 				err = got_object_open_as_blob(&blob2, repo,
-				    id2, 8192);
+				    id2, 8192, fd2);
 				if (err)
 					goto done;
 			}
@@ -860,6 +916,10 @@ diff_paths(struct got_tree_object *tree1, struct got_t
 			err = got_error(GOT_ERR_OBJ_TYPE);
 			goto done;
 		}
+		if (ftruncate(fd1, 0L) == -1)
+			return got_error_from_errno("ftruncate");
+		if (ftruncate(fd2, 0L) == -1)
+			return got_error_from_errno("ftruncate");
 	}
 done:
 	free(id1);
@@ -868,8 +928,12 @@ done:
 		got_object_tree_close(subtree1);
 	if (subtree2)
 		got_object_tree_close(subtree2);
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob1)
 		got_object_blob_close(blob1);
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob2)
 		got_object_blob_close(blob2);
 	return err;
blob - 58f6ea9d97872411048d72595be2da70a1bb58ae
blob + 2ed7fd6f24b77b5c61137092e927591fc46d903d
--- lib/got_lib_object.h
+++ lib/got_lib_object.h
@@ -123,7 +123,7 @@ const struct got_error *got_object_commit_open(struct 
 const struct got_error *got_object_tree_open(struct got_tree_object **,
     struct got_repository *, struct got_object *);
 const struct got_error *got_object_blob_open(struct got_blob_object **,
-    struct got_repository *, struct got_object *, size_t);
+    struct got_repository *, struct got_object *, size_t, int);
 char *got_object_blob_id_str(struct got_blob_object*, char *, size_t);
 const struct got_error *got_object_tag_open(struct got_tag_object **,
     struct got_repository *, struct got_object *);
blob - dda75c34856cd363ca246441656445d61b9d1b0b
blob + ed7818983060b687f4b51c4d4c6eb36f83eaebd9
--- lib/object.c
+++ lib/object.c
@@ -1158,19 +1158,30 @@ got_tree_entry_get_symlink_target(char **link_target, 
 {
 	const struct got_error *err = NULL;
 	struct got_blob_object *blob = NULL;
+	int fd = -1;
 
 	*link_target = NULL;
 
 	if (!got_object_tree_entry_is_symlink(te))
 		return got_error(GOT_ERR_TREE_ENTRY_TYPE);
 
-	err = got_object_open_as_blob(&blob, repo,
-	    got_tree_entry_get_id(te), PATH_MAX);
+	fd = got_opentempfd();
+	if (fd == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
+	err = got_object_open_as_blob(&blob, repo,
+	    got_tree_entry_get_id(te), PATH_MAX, fd);
 	if (err)
-		return err;
+		goto done;
 
 	err = got_object_blob_read_to_str(link_target, blob);
-	got_object_blob_close(blob);
+done:
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
+	if (blob)
+		got_object_blob_close(blob);
 	if (err) {
 		free(*link_target);
 		*link_target = NULL;
@@ -1335,14 +1346,13 @@ read_blob_privsep(uint8_t **outbuf, size_t *size, size
 
 static const struct got_error *
 open_blob(struct got_blob_object **blob, struct got_repository *repo,
-    struct got_object_id *id, size_t blocksize)
+    struct got_object_id *id, size_t blocksize, int outfd)
 {
 	const struct got_error *err = NULL;
 	struct got_packidx *packidx = NULL;
 	int idx;
 	char *path_packfile = NULL;
 	uint8_t *outbuf;
-	int outfd;
 	size_t size, hdrlen;
 	struct stat sb;
 
@@ -1350,10 +1360,6 @@ open_blob(struct got_blob_object **blob, struct got_re
 	if (*blob == NULL)
 		return got_error_from_errno("calloc");
 
-	outfd = got_opentempfd();
-	if (outfd == -1)
-		return got_error_from_errno("got_opentempfd");
-
 	(*blob)->read_buf = malloc(blocksize);
 	if ((*blob)->read_buf == NULL) {
 		err = got_error_from_errno("malloc");
@@ -1396,9 +1402,6 @@ open_blob(struct got_blob_object **blob, struct got_re
 	}
 
 	if (outbuf) {
-		if (close(outfd) == -1 && err == NULL)
-			err = got_error_from_errno("close");
-		outfd = -1;
 		(*blob)->f = fmemopen(outbuf, size, "rb");
 		if ((*blob)->f == NULL) {
 			err = got_error_from_errno("fmemopen");
@@ -1436,25 +1439,25 @@ done:
 		if (*blob) {
 			got_object_blob_close(*blob);
 			*blob = NULL;
-		} else if (outfd != -1)
-			close(outfd);
+		}
 	}
 	return err;
 }
 
 const struct got_error *
 got_object_open_as_blob(struct got_blob_object **blob,
-    struct got_repository *repo, struct got_object_id *id,
-    size_t blocksize)
+    struct got_repository *repo, struct got_object_id *id, size_t blocksize,
+    int outfd)
 {
-	return open_blob(blob, repo, id, blocksize);
+	return open_blob(blob, repo, id, blocksize, outfd);
 }
 
 const struct got_error *
 got_object_blob_open(struct got_blob_object **blob,
-    struct got_repository *repo, struct got_object *obj, size_t blocksize)
+    struct got_repository *repo, struct got_object *obj, size_t blocksize,
+    int outfd)
 {
-	return open_blob(blob, repo, got_object_get_id(obj), blocksize);
+	return open_blob(blob, repo, got_object_get_id(obj), blocksize, outfd);
 }
 
 const struct got_error *
blob - 21ea570c756aff230fd0f3e62994dd72a5ccd74f
blob + 31595194ab14c4f50ce474f207f1af740ea245a4
--- lib/patch.c
+++ lib/patch.c
@@ -585,6 +585,7 @@ open_blob(char **path, FILE **fp, const char *blobid,
 	const struct got_error *err = NULL;
 	struct got_blob_object *blob = NULL;
 	struct got_object_id id, *idptr, *matched_id = NULL;
+	int fd = -1;
 
 	*fp = NULL;
 	*path = NULL;
@@ -602,7 +603,13 @@ open_blob(char **path, FILE **fp, const char *blobid,
 		idptr = &id;
 	}
 
-	err = got_object_open_as_blob(&blob, repo, idptr, 8192);
+	fd = got_opentempfd();
+	if (fd == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
+	err = got_object_open_as_blob(&blob, repo, idptr, 8192, fd);
 	if (err)
 		goto done;
 
@@ -615,6 +622,8 @@ open_blob(char **path, FILE **fp, const char *blobid,
 		goto done;
 
 done:
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	if (matched_id != NULL)
blob - 9e8ef346fc31e5275d6c78d54e556c1c8941f531
blob + b93f4ff7b75be55059af062e067e463d149c116a
--- lib/worktree.c
+++ lib/worktree.c
@@ -1626,7 +1626,7 @@ get_file_status(unsigned char *status, struct stat *sb
 	const struct got_error *err = NULL;
 	struct got_object_id id;
 	size_t hdrlen;
-	int fd = -1;
+	int fd = -1, fd1 = -1;
 	FILE *f = NULL;
 	uint8_t fbuf[8192];
 	struct got_blob_object *blob = NULL;
@@ -1703,7 +1703,12 @@ get_file_status(unsigned char *status, struct stat *sb
 	else
 		memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
 
-	err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
+	fd1 = got_opentempfd();
+	if (fd1 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf), fd1);
 	if (err)
 		goto done;
 
@@ -1766,6 +1771,8 @@ get_file_status(unsigned char *status, struct stat *sb
 	} else if (xbit_differs(ie, sb->st_mode))
 		*status = GOT_STATUS_MODE_CHANGE;
 done:
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	if (f != NULL && fclose(f) == EOF && err == NULL)
@@ -1799,9 +1806,10 @@ update_blob(struct got_worktree *worktree,
 {
 	const struct got_error *err = NULL;
 	struct got_blob_object *blob = NULL;
-	char *ondisk_path;
+	char *ondisk_path = NULL;
 	unsigned char status = GOT_STATUS_NO_CHANGE;
 	struct stat sb;
+	int fd1 = -1, fd2 = -1;
 
 	if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
 		return got_error_from_errno("asprintf");
@@ -1883,7 +1891,12 @@ update_blob(struct got_worktree *worktree,
 		}
 	}
 
-	err = got_object_open_as_blob(&blob, repo, &te->id, 8192);
+	fd1 = got_opentempfd();
+	if (fd1 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	err = got_object_open_as_blob(&blob, repo, &te->id, 8192, fd1);
 	if (err)
 		goto done;
 
@@ -1892,9 +1905,15 @@ update_blob(struct got_worktree *worktree,
 		struct got_blob_object *blob2 = NULL;
 		char *label_orig = NULL;
 		if (got_fileindex_entry_has_blob(ie)) {
+			fd2 = got_opentempfd();
+			if (fd2 == -1) {
+				err = got_error_from_errno("got_opentempfd");
+				goto done;
+			}
 			struct got_object_id id2;
 			memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
-			err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
+			err = got_object_open_as_blob(&blob2, repo, &id2, 8192,
+			    fd2);
 			if (err)
 				goto done;
 		}
@@ -1928,6 +1947,10 @@ update_blob(struct got_worktree *worktree,
 			    progress_cb, progress_arg);
 		}
 		free(label_orig);
+		if (fd2 != -1 && close(fd2) == -1 && err == NULL) {
+			err = got_error_from_errno("close");
+			goto done;
+		}
 		if (blob2)
 			got_object_blob_close(blob2);
 		if (err)
@@ -1986,6 +2009,11 @@ update_blob(struct got_worktree *worktree,
 			    GOT_FILEIDX_MODE_BAD_SYMLINK);
 		}
 	}
+
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL) {
+		err = got_error_from_errno("close");
+		goto done;
+	}
 	got_object_blob_close(blob);
 done:
 	free(ondisk_path);
@@ -4402,7 +4430,7 @@ create_patched_content(char **path_outfile, int revers
 	const struct got_error *err, *free_err;
 	struct got_blob_object *blob = NULL;
 	FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
-	int fd2 = -1;
+	int fd = -1, fd2 = -1;
 	char link_target[PATH_MAX];
 	ssize_t link_len = 0;
 	char *path1 = NULL, *id_str = NULL;
@@ -4480,7 +4508,13 @@ create_patched_content(char **path_outfile, int revers
 		rewind(f2);
 	}
 
-	err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
+	fd = got_opentempfd();
+	if (fd == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
+	err = got_object_open_as_blob(&blob, repo, blob_id, 8192, fd);
 	if (err)
 		goto done;
 
@@ -4544,6 +4578,8 @@ create_patched_content(char **path_outfile, int revers
 	}
 done:
 	free(id_str);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	free_err = got_diffreg_result_free(diffreg_result);
@@ -4586,6 +4622,7 @@ revert_file(void *arg, unsigned char status, unsigned 
 	char *tree_path = NULL, *te_name;
 	char *ondisk_path = NULL, *path_content = NULL;
 	struct got_blob_object *blob = NULL;
+	int fd = -1;
 
 	/* Reverting a staged deletion is a no-op. */
 	if (status == GOT_STATUS_DELETE &&
@@ -4715,7 +4752,13 @@ revert_file(void *arg, unsigned char status, unsigned 
 		} else
 			memcpy(id.sha1, ie->blob_sha1,
 			    SHA1_DIGEST_LENGTH);
-		err = got_object_open_as_blob(&blob, a->repo, &id, 8192);
+		fd = got_opentempfd();
+		if (fd == -1) {
+			err = got_error_from_errno("got_opentempfd");
+			goto done;
+		}
+
+		err = got_object_open_as_blob(&blob, a->repo, &id, 8192, fd);
 		if (err)
 			goto done;
 
@@ -4791,6 +4834,8 @@ done:
 	free(path_content);
 	free(parent_path);
 	free(tree_path);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	if (tree)
@@ -8251,6 +8296,7 @@ create_unstaged_content(char **path_unstaged_content,
 	struct got_diffreg_result *diffreg_result = NULL;
 	int line_cur1 = 1, line_cur2 = 1, n = 0, nchunks_used = 0;
 	int have_content = 0, have_rejected_content = 0, i = 0, nchanges = 0;
+	int fd1 = -1, fd2 = -1;
 
 	*path_unstaged_content = NULL;
 	*path_new_staged_content = NULL;
@@ -8258,7 +8304,19 @@ create_unstaged_content(char **path_unstaged_content,
 	err = got_object_id_str(&label1, blob_id);
 	if (err)
 		return err;
-	err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
+
+	fd1 = got_opentempfd();
+	if (fd1 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
+	err = got_object_open_as_blob(&blob, repo, blob_id, 8192, fd1);
 	if (err)
 		goto done;
 
@@ -8270,7 +8328,8 @@ create_unstaged_content(char **path_unstaged_content,
 	if (err)
 		goto done;
 
-	err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192);
+	err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192,
+	    fd2);
 	if (err)
 		goto done;
 
@@ -8306,7 +8365,7 @@ create_unstaged_content(char **path_unstaged_content,
 	}
 	/* Count the number of actual changes in the diff result. */
 	for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
-		struct diff_chunk_context cc = {}; 
+		struct diff_chunk_context cc = {};
 		diff_chunk_context_load_change(&cc, &nchunks_used,
 		    diffreg_result->result, n, 0);
 		nchanges++;
@@ -8331,8 +8390,12 @@ create_unstaged_content(char **path_unstaged_content,
 		    outfile, rejectfile);
 done:
 	free(label1);
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (staged_blob)
 		got_object_blob_close(staged_blob);
 	free_err = got_diffreg_result_free(diffreg_result);
@@ -8534,6 +8597,7 @@ unstage_path(void *arg, unsigned char status,
 	char *id_str = NULL, *label_orig = NULL;
 	int local_changes_subsumed;
 	struct stat sb;
+	int fd1 = -1, fd2 = -1;
 
 	if (staged_status != GOT_STATUS_ADD &&
 	    staged_status != GOT_STATUS_MODIFY &&
@@ -8555,13 +8619,24 @@ unstage_path(void *arg, unsigned char status,
 	if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
 	    id_str) == -1) {
 		err = got_error_from_errno("asprintf");
+		goto done;
+	}
+
+	fd1 = got_opentempfd();
+	if (fd1 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
 		goto done;
 	}
 
 	switch (staged_status) {
 	case GOT_STATUS_MODIFY:
 		err = got_object_open_as_blob(&blob_base, a->repo,
-		    blob_id, 8192);
+		    blob_id, 8192, fd1);
 		if (err)
 			break;
 		/* fall through */
@@ -8585,7 +8660,7 @@ unstage_path(void *arg, unsigned char status,
 			}
 		}
 		err = got_object_open_as_blob(&blob_staged, a->repo,
-		    staged_blob_id, 8192);
+		    staged_blob_id, 8192, fd2);
 		if (err)
 			break;
 		switch (got_fileindex_entry_staged_filetype_get(ie)) {
@@ -8656,8 +8731,12 @@ unstage_path(void *arg, unsigned char status,
 	}
 done:
 	free(ondisk_path);
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob_base)
 		got_object_blob_close(blob_base);
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob_staged)
 		got_object_blob_close(blob_staged);
 	free(id_str);
blob - 5e7564648c9d9abf1f4532d4cd46c8eb464eb51e
blob + d4eb22343e8c4a8e2363f38b1954b530f978b2fb
--- tog/tog.c
+++ tog/tog.c
@@ -4797,13 +4797,19 @@ run_blame(struct tog_view *view)
 	struct got_blob_object *blob = NULL;
 	struct got_repository *thread_repo = NULL;
 	struct got_object_id *obj_id = NULL;
-	int obj_type;
+	int obj_type, fd = -1;
 	int *pack_fds = NULL;
 
 	err = got_object_open_as_commit(&commit, s->repo,
 	    &s->blamed_commit->id);
 	if (err)
 		return err;
+
+	fd = got_opentempfd();
+	if (fd == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 
 	err = got_object_id_by_path(&obj_id, s->repo, commit, s->path);
 	if (err)
@@ -4818,7 +4824,7 @@ run_blame(struct tog_view *view)
 		goto done;
 	}
 
-	err = got_object_open_as_blob(&blob, s->repo, obj_id, 8192);
+	err = got_object_open_as_blob(&blob, s->repo, obj_id, 8192, fd);
 	if (err)
 		goto done;
 	blame->f = got_opentemp();
@@ -4882,6 +4888,8 @@ run_blame(struct tog_view *view)
 done:
 	if (commit)
 		got_object_commit_close(commit);
+	if (fd != -1 && close(fd) == -1 && err == NULL)
+		err = got_error_from_errno("close");
 	if (blob)
 		got_object_blob_close(blob);
 	free(obj_id);