Commit f9d67749a9af07e9813218e2735bf24262ac77f7

Stefan Sperling 2017-11-30T02:38:38

move tempfile creation out of got_diffreg()

diff --git a/lib/diff.c b/lib/diff.c
index af6392d..d151719 100644
--- a/lib/diff.c
+++ b/lib/diff.c
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include <sha1.h>
 #include <zlib.h>
 
@@ -29,28 +30,24 @@
 
 #include "diff.h"
 
-static const struct got_error *
-open_tempfile(FILE **sfp, char **sfn)
+static FILE *
+opentemp(void)
 {
-	static const int sfnlen = 20;
+	char name[PATH_MAX];
 	int fd;
 
-	*sfn = calloc(sfnlen, sizeof(char));
-	if (*sfn == NULL)
-		return got_error(GOT_ERR_NO_MEM);
-	strlcpy(*sfn, "/tmp/got.XXXXXXXXXX", sfnlen);
-	if ((fd = mkstemp(*sfn)) == -1 ||
-	    ((*sfp) = fdopen(fd, "w+")) == NULL) {
-		if (fd != -1) {
-			unlink(*sfn);
-			close(fd);
-		}
-		free(*sfn);
-		return got_error(GOT_ERR_FILE_OPEN);
-	}
-	return NULL;
+	if (strlcpy(name, "/tmp/got.XXXXXXXX", sizeof(name)) >= sizeof(name))
+		return NULL;
+
+	fd = mkstemp(name);
+	if (fd < 0)
+		return NULL;
+
+	unlink(name);
+	return (fdopen(fd, "w+"));
 }
 
+
 const struct got_error *
 got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
     const char *label1, const char *label2, FILE *outfile)
@@ -59,24 +56,21 @@ got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
 	struct got_diff_args args;
 	const struct got_error *err = NULL;
 	FILE *f1, *f2;
-	char *n1, *n2;
-	size_t len, hdrlen;
 	char hex1[SHA1_DIGEST_STRING_LENGTH];
 	char hex2[SHA1_DIGEST_STRING_LENGTH];
+	size_t len, hdrlen;
 	int res;
 
-	err = open_tempfile(&f1, &n1);
-	if (err != NULL)
-		return err;
+	f1 = opentemp();
+	if (f1 == NULL)
+		return got_error(GOT_ERR_FILE_OPEN);
 
-	err = open_tempfile(&f2, &n2);
-	if (err != NULL) {
+	f2 = opentemp();
+	if (f2 == NULL) {
 		fclose(f1);
-		free(n1);
-		return err;
+		return got_error(GOT_ERR_FILE_OPEN);
 	}
 
-
 	hdrlen = blob1->hdrlen;
 	do {
 		err = got_object_blob_read_block(blob1, &len);
@@ -99,24 +93,30 @@ got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
 
 	fflush(f1);
 	fflush(f2);
+	/* rewind(f1); */
+	/* rewind(f2);*/
 
 	memset(&ds, 0, sizeof(ds));
-	memset(&args, 0, sizeof(args));
+	/* XXX should stat buffers be passed in args instead of ds? */
+	ds.stb1.st_mode = S_IFREG;
+	ds.stb1.st_size = blob1->zb.z.total_out;
+	ds.stb1.st_mtime = 0; /* XXX */
 
+	ds.stb2.st_mode = S_IFREG;
+	ds.stb2.st_size = blob2->zb.z.total_out;
+	ds.stb2.st_mtime = 0; /* XXX */
+
+	memset(&args, 0, sizeof(args));
 	args.diff_format = D_UNIFIED;
 	args.label[0] = label1 ?
 	    label1 : got_object_id_str(&blob1->id, hex1, sizeof(hex1));
 	args.label[1] = label2 ?
 	    label2 : got_object_id_str(&blob2->id, hex2, sizeof(hex2));
 
-	err = got_diffreg(&res, n1, n2, 0, &args, &ds);
+	err = got_diffreg(&res, f1, f2, 0, &args, &ds);
 done:
-	unlink(n1);
-	unlink(n2);
 	fclose(f1);
 	fclose(f2);
-	free(n1);
-	free(n2);
 	return err;
 }
 
diff --git a/lib/diff.h b/lib/diff.h
index 80c64f3..a63e893 100644
--- a/lib/diff.h
+++ b/lib/diff.h
@@ -117,8 +117,8 @@ struct got_diff_args {
 };
 
 char	*splice(char *, char *);
-const struct got_error *got_diffreg(int *, char *,
-    char *, int, struct got_diff_args *, struct got_diff_state *);
+const struct got_error *got_diffreg(int *, FILE *,
+    FILE *, int, struct got_diff_args *, struct got_diff_state *);
 int	easprintf(char **, const char *, ...);
 void	*emalloc(size_t);
 void	*erealloc(void *, size_t);
diff --git a/lib/diffreg.c b/lib/diffreg.c
index b8591d4..1f12b87 100644
--- a/lib/diffreg.c
+++ b/lib/diffreg.c
@@ -184,8 +184,7 @@ struct context_vec {
 };
 
 #define	diff_output	printf
-static FILE	*opentemp(const char *);
-static void	 output(struct got_diff_state *, struct got_diff_args *, char *, FILE *, char *, FILE *, int);
+static void	 output(struct got_diff_state *, struct got_diff_args *, const char *, FILE *, const char *, FILE *, int);
 static void	 check(struct got_diff_state *, FILE *, FILE *, int);
 static void	 range(int, int, char *);
 static void	 uni_range(int, int);
@@ -196,7 +195,7 @@ static void	 prune(struct got_diff_state *);
 static void	 equiv(struct line *, int, struct line *, int, int *);
 static void	 unravel(struct got_diff_state *, int);
 static void	 unsort(struct line *, int, int *);
-static void	 change(struct got_diff_state *, struct got_diff_args *, char *, FILE *, char *, FILE *, int, int, int, int, int *);
+static void	 change(struct got_diff_state *, struct got_diff_args *, const char *, FILE *, const char *, FILE *, int, int, int, int, int *);
 static void	 sort(struct line *, int);
 static void	 print_header(struct got_diff_state *, struct got_diff_args *, const char *, const char *);
 static int	 ignoreline(char *);
@@ -270,26 +269,13 @@ u_char cup2low[256] = {
 	0xfd, 0xfe, 0xff
 };
 
-/* XXX should expect 'FILE *' instead of 'char *' */
 const struct got_error *
-got_diffreg(int *rval, char *file1, char *file2, int flags,
+got_diffreg(int *rval, FILE *f1, FILE *f2, int flags,
     struct got_diff_args *args, struct got_diff_state *ds)
 {
 	const struct got_error *err = NULL;
-	FILE *f1, *f2;
 	int i;
 
-	if (strcmp(file1, "-") == 0)
-		fstat(STDIN_FILENO, &ds->stb1);
-	else if (stat(file1, &ds->stb1) != 0)
-		return got_error(GOT_ERR_BAD_PATH);
-
-	if (strcmp(file2, "-") == 0)
-		fstat(STDIN_FILENO, &ds->stb2);
-	else if (stat(file2, &ds->stb2) != 0)
-		return got_error(GOT_ERR_BAD_PATH);
-
-	f1 = f2 = NULL;
 	*rval = D_SAME;
 	ds->anychange = 0;
 	ds->lastline = 0;
@@ -303,43 +289,16 @@ got_diffreg(int *rval, char *file1, char *file2, int flags,
 		*rval = (S_ISDIR(ds->stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2);
 		return NULL;
 	}
-	if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0)
-		goto closem;
-
 	if (flags & D_EMPTY1)
 		f1 = fopen(_PATH_DEVNULL, "r");
-	else {
-		if (!S_ISREG(ds->stb1.st_mode)) {
-			if ((f1 = opentemp(file1)) == NULL ||
-			    fstat(fileno(f1), &ds->stb1) < 0) {
-				args->status |= 2;
-				goto closem;
-			}
-		} else if (strcmp(file1, "-") == 0)
-			f1 = stdin;
-		else
-			f1 = fopen(file1, "r");
-	}
-	if (f1 == NULL) {
+	else if (f1 == NULL) {
 		args->status |= 2;
 		goto closem;
 	}
 
 	if (flags & D_EMPTY2)
 		f2 = fopen(_PATH_DEVNULL, "r");
-	else {
-		if (!S_ISREG(ds->stb2.st_mode)) {
-			if ((f2 = opentemp(file2)) == NULL ||
-			    fstat(fileno(f2), &ds->stb2) < 0) {
-				args->status |= 2;
-				goto closem;
-			}
-		} else if (strcmp(file2, "-") == 0)
-			f2 = stdin;
-		else
-			f2 = fopen(file2, "r");
-	}
-	if (f2 == NULL) {
+	else if (f2 == NULL) {
 		args->status |= 2;
 		goto closem;
 	}
@@ -422,7 +381,7 @@ got_diffreg(int *rval, char *file1, char *file2, int flags,
 		goto closem;
 	}
 	check(ds, f1, f2, flags);
-	output(ds, args, file1, f1, file2, f2, flags);
+	output(ds, args, args->label[0], f1, args->label[1], f2, flags);
 closem:
 	if (ds->anychange) {
 		args->status |= 1;
@@ -465,37 +424,6 @@ files_differ(struct got_diff_state *ds, FILE *f1, FILE *f2, int flags)
 	}
 }
 
-static FILE *
-opentemp(const char *file)
-{
-	char buf[BUFSIZ], tempfile[PATH_MAX];
-	ssize_t nread;
-	int ifd, ofd;
-
-	if (strcmp(file, "-") == 0)
-		ifd = STDIN_FILENO;
-	else if ((ifd = open(file, O_RDONLY, 0644)) < 0)
-		return (NULL);
-
-	(void)strlcpy(tempfile, _PATH_TMP "/diff.XXXXXXXX", sizeof(tempfile));
-
-	if ((ofd = mkstemp(tempfile)) < 0) {
-		close(ifd);
-		return (NULL);
-	}
-	unlink(tempfile);
-	while ((nread = read(ifd, buf, BUFSIZ)) > 0) {
-		if (write(ofd, buf, nread) != nread) {
-			close(ifd);
-			close(ofd);
-			return (NULL);
-		}
-	}
-	close(ifd);
-	lseek(ofd, (off_t)0, SEEK_SET);
-	return (fdopen(ofd, "r"));
-}
-
 char *
 splice(char *dir, char *file)
 {
@@ -874,7 +802,7 @@ skipline(FILE *f)
 
 static void
 output(struct got_diff_state *ds, struct got_diff_args *args,
-    char *file1, FILE *f1, char *file2, FILE *f2, int flags)
+    const char *file1, FILE *f1, const char *file2, FILE *f2, int flags)
 {
 	int m, i0, i1, j0, j1;
 
@@ -976,7 +904,7 @@ ignoreline(char *line)
  */
 static void
 change(struct got_diff_state *ds, struct got_diff_args *args,
-    char *file1, FILE *f1, char *file2, FILE *f2,
+    const char *file1, FILE *f1, const char *file2, FILE *f2,
     int a, int b, int c, int d, int *pflags)
 {
 	static size_t max_context = 64;