git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Careful object pulling

From
Daniel Barkalow <barkalow@iabervon.org>
Date
May 4, 2005, 04:07 UTC
Message-ID
<Pine.LNX.4.21.0505040004290.30848-100000@iabervon.org>
In-Reply-To
<Pine.LNX.4.58.0505031204030.26698@ppc970.osdl.org>

This splits out the careful methods for writing a file and placing it in the correct location from the function to write a buffer to the file and makes the various functions used by git-*-pull programs use those functions to write their files.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Index: cache.h
===================================================================
--- 51a882a2dc62e0d3cdc79e0badc61559fb723481/cache.h  (mode:100644 sha1:8dd812827604d510038f5d93e3718c43f9d12c30)
+++ 4e31436bacfff09ce673665a1061b41e37ffd661/cache.h  (mode:100644 sha1:0d7411c3b86a899cee45627997f4bb7ba0df2ea7)
@@ -134,6 +134,12 @@
 extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
 extern int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned char *return_sha1);
 
+/* Open a file for writing a sha1 file. */
+extern int open_sha1_tmpfile(char tmpfile[PATH_MAX]);
+
+/* Put a sha1 file in the correct place. */
+extern int place_sha1_file(char tmpfile[PATH_MAX], const unsigned char *sha1);
+
 extern int check_sha1_signature(unsigned char *sha1, void *buf, unsigned long size, const char *type);
 
 /* Read a tree into the cache */
Index: http-pull.c
===================================================================
--- 51a882a2dc62e0d3cdc79e0badc61559fb723481/http-pull.c  (mode:100644 sha1:f693aba61b4dcb4b738faf1335ec74aa1545e45d)
+++ 4e31436bacfff09ce673665a1061b41e37ffd661/http-pull.c  (mode:100644 sha1:793d8b9e125c1f164f774e2888d26beaa75e1df0)
@@ -52,8 +52,9 @@
 	char real_sha1[20];
 	char *url;
 	char *posn;
+	char tmpname[PATH_MAX];
 
-	local = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
+	local = open_sha1_tmpfile(tmpname);
 
 	if (local < 0)
 		return error("Couldn't open %s\n", filename);
@@ -88,15 +89,14 @@
 	inflateEnd(&stream);
 	SHA1_Final(real_sha1, &c);
 	if (zret != Z_STREAM_END) {
-		unlink(filename);
+		unlink(tmpname);
 		return error("File %s (%s) corrupt\n", hex, url);
 	}
 	if (memcmp(sha1, real_sha1, 20)) {
-		unlink(filename);
+		unlink(tmpname);
 		return error("File %s has bad hash\n", hex);
 	}
-	
-	return 0;
+	return place_sha1_file(tmpname, sha1);
 }
 
 int main(int argc, char **argv)
Index: sha1_file.c
===================================================================
--- 51a882a2dc62e0d3cdc79e0badc61559fb723481/sha1_file.c  (mode:100644 sha1:e6ce455ae90bd430f2128f454bdb6e0575412486)
+++ 4e31436bacfff09ce673665a1061b41e37ffd661/sha1_file.c  (mode:100644 sha1:85daa0b0045c3f19e697d1a7aa8ab15ff54eab99)
@@ -276,6 +276,55 @@
 	}
 }
 
+int open_sha1_tmpfile(char tmpfile[PATH_MAX])
+{
+	int fd;
+
+	snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
+	fd = mkstemp(tmpfile);
+	if (fd < 0) {
+		fprintf(stderr,
+			"unable to create temporary sha1 filename %s: %s",
+			tmpfile, strerror(errno));
+		return -1;
+	}
+	return fd;
+}
+
+int place_sha1_file(char tmpfile[PATH_MAX], const unsigned char *sha1)
+{
+	char *filename = sha1_file_name(sha1);
+	int ret;
+
+	ret = link(tmpfile, filename);
+	if (ret < 0) {
+		ret = errno;
+
+		/*
+		 * Coda hack - coda doesn't like cross-directory links,
+		 * so we fall back to a rename, which will mean that it
+		 * won't be able to check collisions, but that's not a
+		 * big deal.
+		 *
+		 * When this succeeds, we just return 0. We have nothing
+		 * left to unlink.
+		 */
+		if (ret == EXDEV && !rename(tmpfile, filename))
+			return 0;
+	}
+	unlink(tmpfile);
+	if (ret) {
+		if (ret != EEXIST) {
+			fprintf(stderr,
+				"unable to write sha1 filename %s: %s", 
+				filename, strerror(ret));
+			return -1;
+		}
+		/* FIXME!!! Collision check here ? */
+	}
+	return 0;
+}
+
 int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned char *returnsha1)
 {
 	int size;
@@ -286,7 +335,7 @@
 	char *filename;
 	static char tmpfile[PATH_MAX];
 	char hdr[50];
-	int fd, hdrlen, ret;
+	int fd, hdrlen;
 
 	/* Generate the header */
 	hdrlen = sprintf(hdr, "%s %lu", type, len)+1;
@@ -316,12 +365,9 @@
 		return -1;
 	}
 
-	snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
-	fd = mkstemp(tmpfile);
-	if (fd < 0) {
-		fprintf(stderr, "unable to create temporary sha1 filename %s: %s", tmpfile, strerror(errno));
-		return -1;
-	}
+	fd = open_sha1_tmpfile(tmpfile);
+	if (fd < 0)
+		return fd;
 
 	/* Set it up */
 	memset(&stream, 0, sizeof(stream));
@@ -349,53 +395,28 @@
 
 	if (write(fd, compressed, size) != size)
 		die("unable to write file");
+
 	fchmod(fd, 0444);
 	close(fd);
 
-	ret = link(tmpfile, filename);
-	if (ret < 0) {
-		ret = errno;
-
-		/*
-		 * Coda hack - coda doesn't like cross-directory links,
-		 * so we fall back to a rename, which will mean that it
-		 * won't be able to check collisions, but that's not a
-		 * big deal.
-		 *
-		 * When this succeeds, we just return 0. We have nothing
-		 * left to unlink.
-		 */
-		if (ret == EXDEV && !rename(tmpfile, filename))
-			return 0;
-	}
-	unlink(tmpfile);
-	if (ret) {
-		if (ret != EEXIST) {
-			fprintf(stderr, "unable to write sha1 filename %s: %s", filename, strerror(ret));
-			return -1;
-		}
-		/* FIXME!!! Collision check here ? */
-	}
-
-	return 0;
+	return place_sha1_file(tmpfile, sha1);
 }
 
 int write_sha1_from_fd(const unsigned char *sha1, int fd)
 {
-	char *filename = sha1_file_name(sha1);
-
 	int local;
 	z_stream stream;
 	unsigned char real_sha1[20];
 	char buf[4096];
 	char discard[4096];
+	char tmpname[PATH_MAX];
 	int ret;
 	SHA_CTX c;
 
-	local = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
+	local = open_sha1_tmpfile(tmpname);
 
 	if (local < 0)
-		return error("Couldn't open %s\n", filename);
+		return -1;
 
 	memset(&stream, 0, sizeof(stream));
 
@@ -408,7 +429,7 @@
 		size = read(fd, buf, 4096);
 		if (size <= 0) {
 			close(local);
-			unlink(filename);
+			unlink(tmpname);
 			if (!size)
 				return error("Connection closed?");
 			perror("Reading from connection");
@@ -431,15 +452,15 @@
 	close(local);
 	SHA1_Final(real_sha1, &c);
 	if (ret != Z_STREAM_END) {
-		unlink(filename);
+		unlink(tmpname);
 		return error("File %s corrupted", sha1_to_hex(sha1));
 	}
 	if (memcmp(sha1, real_sha1, 20)) {
-		unlink(filename);
+		unlink(tmpname);
 		return error("File %s has bad hash\n", sha1_to_hex(sha1));
 	}
-	
-	return 0;
+
+	return place_sha1_file(tmpname, sha1);
 }
 
 int has_sha1_file(const unsigned char *sha1)
Previous: Junio C HamanoNext: Morten Welinder
Message 17 of 19 in “Careful object writing..”
  1. Linus TorvaldsMay 3, 2005
  2. Chris WedgwoodMay 3, 2005
  3. Linus TorvaldsMay 3, 2005
  4. Chris WedgwoodMay 3, 2005
  5. Linus TorvaldsMay 3, 2005
  6. Daniel BarkalowMay 3, 2005
  7. Jan HarkesMay 3, 2005
  8. Linus TorvaldsMay 3, 2005
  9. Jan HarkesMay 3, 2005
  10. Linus TorvaldsMay 3, 2005
  11. Linus TorvaldsMay 3, 2005
  12. H. Peter AnvinMay 3, 2005
  13. Alex RiesenMay 3, 2005
  14. Linus TorvaldsMay 3, 2005
  15. Alex RiesenMay 3, 2005
  16. Junio C HamanoMay 3, 2005
  17. Careful object pullingDaniel Barkalow, May 4, 2005
  18. Morten WelinderMay 4, 2005
  19. Daniel BarkalowMay 4, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.