Subject: Re: PATCH: refactor memstream for "print -v"
From: "Jun T." <[email-masked]>
To: [email-masked]
Date: Wed, 6 Jan 2016 01:31:03 +0900
List-Id: Zsh Workers List <zsh-workers.zsh.org>

The patch below is against 37503+37504.

The first part of the second hank is to deal with a rare case
that gettempfile() succeeds but fdopen() fails.

The last part (READ_MSTREAM) is for not adding a trailing NULL
to buf. The cast (int)count is just to silence the following
warning from clang:

builtin.c:4435:56: warning: comparison of unsigned expression < 0 is always
      false [-Wtautological-compare]
        if (IS_MSTREAM(fout) && READ_MSTREAM(buf,rcount,fout) < 0)
                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~

diff --git a/Src/builtin.c b/Src/builtin.c
index 2201184..e04f090 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4028,7 +4028,7 @@ bin_print(char *name, char **args, Options ops, int func)
     size_t mcount;
 #define ASSIGN_MSTREAM(BUF,FOUT) \
     do { \
-        if ((fout = open_memstream(&BUF, &mcount)) == NULL) { \
+        if ((FOUT = open_memstream(&BUF, &mcount)) == NULL) { \
             zwarnnam(name, "open_memstream failed"); \
             return 1; \
         } \
@@ -4049,17 +4049,21 @@ bin_print(char *name, char **args, Options ops, int func)
     do { \
         int tempfd; \
         char *tmpf; \
-        if ((tempfd = gettempfile(NULL, 1, &tmpf)) < 0 || \
-            (fout = fdopen(tempfd, "w+")) == NULL) { \
-            zwarnnam(name, "can't open temp file: %e", errno); \
-            return 1; \
-        } \
-        unlink(tmpf); \
+	if ((tempfd = gettempfile(NULL, 1, &tmpf)) < 0) { \
+	    zwarnnam(name, "can't create temp file: %e", errno); \
+	    return 1; \
+	} \
+	unlink(tmpf); \
+	if ((fout = fdopen(tempfd, "w+")) == NULL) { \
+	    close(tempfd);  \
+	    zwarnnam(name, "can't open temp file: %e", errno); \
+	    return 1; \
+	} \
     } while (0)
 #define READ_MSTREAM(BUF,COUNT,FOUT) \
-    ((((count = ftell(FOUT)), (BUF = (char *)zalloc(count + 1))) && \
-      ((fseek(FOUT, 0L, SEEK_SET) == 0) && !(BUF[count] = '\0')) && \
-      ((COUNT = fread(BUF, 1, count, FOUT)) == count)) ? count : -1)
+    ((((count = ftell(FOUT)), (BUF = (char *)zalloc(count))) && \
+      (fseek(FOUT, 0L, SEEK_SET) == 0) && \
+      ((COUNT = fread(BUF, 1, count, FOUT)) == count)) ? (int)count : -1)
 #define CLOSE_MSTREAM(FOUT) fclose(FOUT)
 
 #endif