Re: [PATCH 2/7] nfv?asprintf are broken without va_copy, workaround them.

Previous thread: none

Next thread: [PATCH 3/7] strbuf API additions and enhancements. by Pierre Habouzit on Wednesday, September 19, 2007 - 3:42 pm. (3 messages)
From: Pierre Habouzit
Date: Wednesday, September 19, 2007 - 3:42 pm

Here is the take 3. wrt last time: the need for strbuf_addvf has been
avoided. It was not really needed for many places, and I chose ad-hoc
solutions for each. It has been done in a new patch (inserted at slot
2).

  Note that this patch 2/7 looks curious, especially the:

  write_fd_or_whine(..., "\n", 1, ...)

  it is rewritten in a following patch in the series, it's just to have
an intermediate working state. Don't really mind the bad look of it,
please :).


  As a consequence, strbuf_addvf is no longer added nor used in the
series.

  I just rebased it on the last next (with the new git-fetch).



-

From: Pierre Habouzit
Date: Wednesday, September 19, 2007 - 3:42 pm

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
 archive-tar.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/archive-tar.c b/archive-tar.c
index a87bc4b..e1bced5 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -238,15 +238,14 @@ static int write_tar_entry(const unsigned char *sha1,
                            const char *filename, unsigned mode, int stage)
 {
 	static struct strbuf path = STRBUF_INIT;
-	int filenamelen = strlen(filename);
 	void *buffer;
 	enum object_type type;
 	unsigned long size;
 
-	strbuf_grow(&path, MAX(PATH_MAX, baselen + filenamelen + 1));
 	strbuf_reset(&path);
+	strbuf_grow(&path, PATH_MAX);
 	strbuf_add(&path, base, baselen);
-	strbuf_add(&path, filename, filenamelen);
+	strbuf_addstr(&path, filename);
 	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
 		strbuf_addch(&path, '/');
 		buffer = NULL;
-- 
1.5.3.2.1036.gccf7

-

From: Pierre Habouzit
Date: Wednesday, September 19, 2007 - 3:42 pm

* drop nfasprintf.
* move nfvasprintf into imap-send.c back, and let it work on a 8k buffer,
  and die() in case of overflow. It should be enough for imap commands, if
  someone cares about imap-send, he's welcomed to fix it properly.
* replace nfvasprintf use in merge-recursive with a copy of the strbuf_addf
  logic, it's one place, we'll live with it.
  To ease the change, output_buffer string list is replaced with a strbuf ;)
* rework trace.c API's so that only one of the trace functions takes a
  vararg. It's used to format strerror()s and git command names, it should
  never be more than a few octets long, let it work on a 8k static buffer
  with vsnprintf or die loudly.

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
 cache.h           |    4 +--
 exec_cmd.c        |    3 +-
 git.c             |    8 +++---
 imap-send.c       |   13 +++++++++
 merge-recursive.c |   74 +++++++++++++++++++++++---------------------------
 trace.c           |   78 +++++++++++-----------------------------------------
 6 files changed, 71 insertions(+), 109 deletions(-)

diff --git a/cache.h b/cache.h
index c57ccd6..9863917 100644
--- a/cache.h
+++ b/cache.h
@@ -587,10 +587,8 @@ extern void *alloc_object_node(void);
 extern void alloc_report(void);
 
 /* trace.c */
-extern int nfasprintf(char **str, const char *fmt, ...);
-extern int nfvasprintf(char **str, const char *fmt, va_list va);
 extern void trace_printf(const char *format, ...);
-extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
+extern void trace_argv(const char **argv, int count);
 
 /* convert.c */
 /* returns 1 if *dst was used */
diff --git a/exec_cmd.c b/exec_cmd.c
index 9b74ed2..c0f954e 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -97,7 +97,8 @@ int execv_git_cmd(const char **argv)
 		tmp = argv[0];
 		argv[0] = git_command;
 
-		trace_argv_printf(argv, -1, "trace: exec:");
+		trace_printf("trace: exec:");
+		trace_argv(argv, -1);
 
 		/* execve() can only ever ...
From: Junio C Hamano
Date: Wednesday, September 19, 2007 - 9:27 pm

and I'd agree with this in principle, there is a minor nit with

This used to be a single call into trace.c which would format a
single string to write(2) out.  Now these two messages go
through separate write(2) and can be broken up.  I think the
atomicity of the log/trace message was the primary reason the
original had such a strange calling convention.

-

From: Christian Couder
Date: Wednesday, September 19, 2007 - 9:53 pm

That's right.

Christian.


-

From: Pierre Habouzit
Date: Thursday, September 20, 2007 - 1:27 am

Okay, given that the formats (as you can see) are always very short,
and that it will always fit in a big enough static buffer, I'll
reinstate this and use a vsnprintf twice then.

--=20
=C2=B7O=C2=B7  Pierre Habouzit
=C2=B7=C2=B7O                                                madcoder@debia=
n.org
OOO                                                http://www.madism.org
From: Pierre Habouzit
Date: Thursday, September 20, 2007 - 1:43 am

* drop nfasprintf.
* move nfvasprintf into imap-send.c back, and let it work on a 8k buffer,
  and die() in case of overflow. It should be enough for imap commands, if
  someone cares about imap-send, he's welcomed to fix it properly.
* replace nfvasprintf use in merge-recursive with a copy of the strbuf_addf
  logic, it's one place, we'll live with it.
  To ease the change, output_buffer string list is replaced with a strbuf ;)
* rework trace.c to call vsnprintf itself.  It's used to format strerror()s
  and git command names, it should never be more than a few octets long, let
  it work on a 8k static buffer with vsnprintf or die loudly.

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---

  This reinstates the trace_argv_printf API. The implementation is
stupid, but is rewritten in a latter commit. I didn't wanted to bother
optimizing it.


 cache.h           |    2 -
 imap-send.c       |   13 ++++++++
 merge-recursive.c |   74 ++++++++++++++++++++-----------------------
 trace.c           |   90 ++++++++++++++++-------------------------------------
 4 files changed, 74 insertions(+), 105 deletions(-)

diff --git a/cache.h b/cache.h
index c57ccd6..b127c43 100644
--- a/cache.h
+++ b/cache.h
@@ -587,8 +587,6 @@ extern void *alloc_object_node(void);
 extern void alloc_report(void);
 
 /* trace.c */
-extern int nfasprintf(char **str, const char *fmt, ...);
-extern int nfvasprintf(char **str, const char *fmt, va_list va);
 extern void trace_printf(const char *format, ...);
 extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
 
diff --git a/imap-send.c b/imap-send.c
index 905d097..e95cdde 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -105,6 +105,19 @@ static void free_generic_messages( message_t * );
 
 static int nfsnprintf( char *buf, int blen, const char *fmt, ... );
 
+static int nfvasprintf(char **strp, const char *fmt, va_list ap)
+{
+	int len;
+	char tmp[8192];
+
+	len = vsnprintf(tmp, sizeof(tmp), fmt, ap);
+	if ...
From: Junio C Hamano
Date: Thursday, September 20, 2007 - 11:17 pm

This assumes obuf.buf has necessary indentations and line

Yuck, this single if statement covers the entirety of the
function.  Let's do

	if (!show(v))


And you overwrite whatever used to be in the buffer, including
the previous buffered message and indentation you added.  Not
nice...

I'll squash this on top of yours for now.

 merge-recursive.c |   45 +++++++++++++++++++++++----------------------
 1 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index 4e27549..86767e6 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -108,34 +108,35 @@ static void flush_output(void)
 
 static void output(int v, const char *fmt, ...)
 {
-	if (show(v)) {
-		int len;
-		va_list ap;
+	int len;
+	va_list ap;
 
-		strbuf_grow(&obuf, call_depth);
-		memset(obuf.buf + obuf.len, ' ', call_depth);
-		strbuf_setlen(&obuf, obuf.len + call_depth);
+	if (!show(v))
+		return;
+
+	strbuf_grow(&obuf, call_depth * 2 + 2);
+	memset(obuf.buf + obuf.len, ' ', call_depth * 2);
+	strbuf_setlen(&obuf, obuf.len + call_depth * 2);
+
+	va_start(ap, fmt);
+	len = vsnprintf(obuf.buf + obuf.len, strbuf_avail(&obuf), fmt, ap);
+	va_end(ap);
 
+	if (len < 0)
+		len = 0;
+	if (len >= strbuf_avail(&obuf)) {
+		strbuf_grow(&obuf, len + 2);
 		va_start(ap, fmt);
-		len = vsnprintf(obuf.buf, strbuf_avail(&obuf) + 1, fmt, ap);
+		len = vsnprintf(obuf.buf + obuf.len, strbuf_avail(&obuf), fmt, ap);
 		va_end(ap);
-
-		if (len < 0)
-			len = 0;
-		if (len > strbuf_avail(&obuf)) {
-			strbuf_grow(&obuf, len);
-			va_start(ap, fmt);
-			len = vsnprintf(obuf.buf, strbuf_avail(&obuf) + 1, fmt, ap);
-			va_end(ap);
-			if (len > strbuf_avail(&obuf)) {
-				die("this should not happen, your snprintf is broken");
-			}
+		if (len >= strbuf_avail(&obuf)) {
+			die("this should not happen, your snprintf is broken");
 		}
-
-		strbuf_setlen(&obuf, obuf.len + len);
-		if (!buffer_output)
-			flush_output();
 	}
+	strbuf_setlen(&obuf, ...
From: Pierre Habouzit
Date: Friday, September 21, 2007 - 12:02 am

--=20
=C2=B7O=C2=B7  Pierre Habouzit
=C2=B7=C2=B7O                                                madcoder@debia=
n.org
OOO                                                http://www.madism.org
From: Pierre Habouzit
Date: Thursday, September 20, 2007 - 1:44 am

* sq_quote_buf is made public, and works on a strbuf.
* sq_quote_argv also works on a strbuf.
* make sq_quote_argv take a "maxlen" argument to check the buffer won't grow
  too big.

Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
 connect.c |   21 ++++++--------
 git.c     |   16 +++-------
 quote.c   |   94 +++++++++++++++------------------------------------------=
---
 quote.h   |    9 ++----
 trace.c   |   25 +++++++---------
 5 files changed, 52 insertions(+), 113 deletions(-)

diff --git a/connect.c b/connect.c
index 1653a0e..06d279e 100644
--- a/connect.c
+++ b/connect.c
@@ -577,16 +577,13 @@ pid_t git_connect(int fd[2], char *url, const char *p=
rog, int flags)
 	if (pid < 0)
 		die("unable to fork");
 	if (!pid) {
-		char command[MAX_CMD_LEN];
-		char *posn =3D command;
-		int size =3D MAX_CMD_LEN;
-		int of =3D 0;
+		struct strbuf cmd;
=20
-		of |=3D add_to_string(&posn, &size, prog, 0);
-		of |=3D add_to_string(&posn, &size, " ", 0);
-		of |=3D add_to_string(&posn, &size, path, 1);
-
-		if (of)
+		strbuf_init(&cmd, MAX_CMD_LEN);
+		strbuf_addstr(&cmd, prog);
+		strbuf_addch(&cmd, ' ');
+		sq_quote_buf(&cmd, path);
+		if (cmd.len >=3D MAX_CMD_LEN)
 			die("command line too long");
=20
 		dup2(pipefd[1][0], 0);
@@ -606,10 +603,10 @@ pid_t git_connect(int fd[2], char *url, const char *p=
rog, int flags)
 				ssh_basename++;
=20
 			if (!port)
-				execlp(ssh, ssh_basename, host, command, NULL);
+				execlp(ssh, ssh_basename, host, cmd.buf, NULL);
 			else
 				execlp(ssh, ssh_basename, "-p", port, host,
-				       command, NULL);
+				       cmd.buf, NULL);
 		}
 		else {
 			unsetenv(ALTERNATE_DB_ENVIRONMENT);
@@ -618,7 +615,7 @@ pid_t git_connect(int fd[2], char *url, const char *pro=
g, int flags)
 			unsetenv(GIT_WORK_TREE_ENVIRONMENT);
 			unsetenv(GRAFT_ENVIRONMENT);
 			unsetenv(INDEX_ENVIRONMENT);
-			execlp("sh", "sh", "-c", command, NULL);
+			execlp("sh", "sh", "-c", cmd.buf, NULL);
 		}
 		die("exec failed");
 ...
Previous thread: none

Next thread: [PATCH 3/7] strbuf API additions and enhancements. by Pierre Habouzit on Wednesday, September 19, 2007 - 3:42 pm. (3 messages)