"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Tracey Emery <tracey@traceyemery.net>
Subject:
Re: move got_opentempfd out of open_blob
To:
gameoftrees@openbsd.org
Date:
Tue, 28 Jun 2022 06:59:53 -0600

Download raw body.

Thread
On Tue, Jun 28, 2022 at 06:14:50AM -0600, Tracey Emery wrote:

Holy crap, how about we try to work on ALL the things.

-- 

Tracey Emery

diff /home/tracey/src/got
commit - db0dfdd7e5c2c5a38ed7c3291a0615132bcb5945
path + /home/tracey/src/got
blob - 64274b1e95d79a3dbf5649704740d1ec966b24fc
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -3548,9 +3548,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();
@@ -3560,7 +3571,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;
 
@@ -3575,8 +3586,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");
@@ -4619,7 +4634,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;
@@ -4684,11 +4699,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);
@@ -4701,7 +4722,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;
 	}
@@ -4717,7 +4739,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;
@@ -4764,12 +4786,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)
@@ -5292,10 +5316,14 @@ 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));
 
 #ifndef PROFILE
@@ -5446,7 +5474,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();
@@ -5488,6 +5516,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)
@@ -12229,13 +12259,22 @@ cat_blob(struct got_object_id *id, struct got_reposito
 {
 	const struct got_error *err;
 	struct got_blob_object *blob;
+	int fd = -1;
 
-	err = got_object_open_as_blob(&blob, repo, id, 8192);
+	fd = got_opentempfd();
+	if (fd == -1)
+		return got_error_from_errno("got_opentempfd");
+
+	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 - a6bd0096cd2d6e29e21d56f19ed44cd2365eb1ba
file + gotweb/gotweb.c
--- gotweb/gotweb.c
+++ gotweb/gotweb.c
@@ -4064,9 +4064,13 @@ 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));
 
 	if (asprintf(&path, "%s%s%s",
@@ -4109,7 +4113,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;
 
@@ -4150,6 +4155,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++) {
@@ -4177,11 +4184,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 ? "/" : "",
@@ -4222,7 +4233,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;
 
@@ -4258,6 +4270,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
file + include/got_object.h
--- 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 - 5e6b96770dafdf895ef7140b2fc28b3d2c8e370b
file + lib/blame.c
--- lib/blame.c
+++ lib/blame.c
@@ -204,6 +204,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)
@@ -215,6 +216,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;
@@ -226,7 +233,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;
 
@@ -273,6 +280,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;
@@ -507,9 +516,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);
@@ -520,7 +533,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;
 
@@ -632,6 +645,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 - 773169c32d3cb119ac330201afe43d53b115085a
file + lib/diff.c
--- 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
file + lib/got_lib_object.h
--- 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 - 06dc960b0d46db574b800f47ce6891fc926fa989
file + lib/object.c
--- lib/object.c
+++ lib/object.c
@@ -1160,19 +1160,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);
 
+	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);
+	    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;
@@ -1337,14 +1348,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;
 
@@ -1352,10 +1362,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");
@@ -1398,9 +1404,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");
@@ -1438,25 +1441,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 - 1bc4c535c2483d8ebfffd91a5553da6d6da60ce8
file + lib/patch.c
--- lib/patch.c
+++ lib/patch.c
@@ -588,6 +588,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;
@@ -605,7 +606,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;
 
@@ -618,6 +625,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 - ae1ce6d136c77ab98e72f28c8a75c47893044c9b
file + lib/worktree.c
--- lib/worktree.c
+++ lib/worktree.c
@@ -1629,7 +1629,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;
@@ -1706,7 +1706,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;
 
@@ -1769,6 +1774,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)
@@ -1802,9 +1809,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");
@@ -1886,7 +1894,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;
 
@@ -1895,9 +1908,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;
 		}
@@ -1931,6 +1950,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)
@@ -1989,6 +2012,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);
@@ -4405,7 +4433,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;
@@ -4483,7 +4511,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;
 
@@ -4547,6 +4581,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);
@@ -4589,6 +4625,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 &&
@@ -4718,7 +4755,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;
 
@@ -4794,6 +4837,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)
@@ -8254,6 +8299,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;
@@ -8261,7 +8307,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;
 
@@ -8273,7 +8331,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;
 
@@ -8309,7 +8368,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++;
@@ -8334,8 +8393,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);
@@ -8537,6 +8600,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 &&
@@ -8561,10 +8625,21 @@ unstage_path(void *arg, unsigned char status,
 		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 */
@@ -8588,7 +8663,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)) {
@@ -8659,8 +8734,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 - e63f4a7c65678ce2cdbd63fb24abb940c2551358
file + tog/tog.c
--- tog/tog.c
+++ tog/tog.c
@@ -4780,7 +4780,7 @@ 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,
@@ -4788,6 +4788,12 @@ run_blame(struct tog_view *view)
 	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)
 		goto done;
@@ -4801,7 +4807,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();
@@ -4865,6 +4871,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);