diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | diff.c | 47 | ||||
-rw-r--r-- | quote.c | 41 | ||||
-rw-r--r-- | quote.h | 26 |
4 files changed, 76 insertions, 41 deletions
@@ -65,6 +65,9 @@ LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h LIB_H += strbuf.h LIB_OBJS += strbuf.o +LIB_H += quote.h +LIB_OBJS += quote.o + LIB_H += diff.h count-delta.h LIB_OBJS += diff.o diffcore-rename.o diffcore-pickaxe.o diffcore-pathspec.o \ count-delta.o diffcore-break.o diffcore-order.o @@ -5,6 +5,7 @@ #include <sys/wait.h> #include <signal.h> #include "cache.h" +#include "quote.h" #include "diff.h" #include "diffcore.h" @@ -40,42 +41,6 @@ static const char *external_diff(void) return external_diff_cmd; } -/* Help to copy the thing properly quoted for the shell safety. - * any single quote is replaced with '\'', and the caller is - * expected to enclose the result within a single quote pair. - * - * E.g. - * original sq_expand result - * name ==> name ==> 'name' - * a b ==> a b ==> 'a b' - * a'b ==> a'\''b ==> 'a'\''b' - */ -static char *sq_expand(const char *src) -{ - static char *buf = NULL; - int cnt, c; - const char *cp; - char *bp; - - /* count bytes needed to store the quoted string. */ - for (cnt = 1, cp = src; *cp; cnt++, cp++) - if (*cp == '\'') - cnt += 3; - - buf = xmalloc(cnt); - bp = buf; - while ((c = *src++)) { - if (c != '\'') - *bp++ = c; - else { - bp = strcpy(bp, "'\\''"); - bp += 4; - } - } - *bp = 0; - return buf; -} - static struct diff_tempfile { const char *name; /* filename external diff should read from */ char hex[41]; @@ -167,16 +132,16 @@ static void builtin_diff(const char *name_a, int complete_rewrite) { int i, next_at, cmd_size; - const char *diff_cmd = "diff -L'%s%s' -L'%s%s'"; - const char *diff_arg = "'%s' '%s'||:"; /* "||:" is to return 0 */ + const char *diff_cmd = "diff -L%s%s -L%s%s"; + const char *diff_arg = "%s %s||:"; /* "||:" is to return 0 */ const char *input_name_sq[2]; const char *path0[2]; const char *path1[2]; const char *name_sq[2]; char *cmd; - name_sq[0] = sq_expand(name_a); - name_sq[1] = sq_expand(name_b); + name_sq[0] = sq_quote(name_a); + name_sq[1] = sq_quote(name_b); /* diff_cmd and diff_arg have 6 %s in total which makes * the sum of these strings 12 bytes larger than required. @@ -186,7 +151,7 @@ static void builtin_diff(const char *name_a, cmd_size = (strlen(diff_cmd) + strlen(diff_opts) + strlen(diff_arg) - 9); for (i = 0; i < 2; i++) { - input_name_sq[i] = sq_expand(temp[i].name); + input_name_sq[i] = sq_quote(temp[i].name); if (!strcmp(temp[i].name, "/dev/null")) { path0[i] = "/dev/null"; path1[i] = ""; diff --git a/quote.c b/quote.c new file mode 100644 index 0000000000..5e6fda311c --- /dev/null +++ b/quote.c @@ -0,0 +1,41 @@ +#include "cache.h" +#include "quote.h" + +/* Help to copy the thing properly quoted for the shell safety. + * any single quote is replaced with '\'', and the caller is + * expected to enclose the result within a single quote pair. + * + * E.g. + * original sq_quote result + * name ==> name ==> 'name' + * a b ==> a b ==> 'a b' + * a'b ==> a'\''b ==> 'a'\''b' + */ +char *sq_quote(const char *src) +{ + static char *buf = NULL; + int cnt, c; + const char *cp; + char *bp; + + /* count bytes needed to store the quoted string. */ + for (cnt = 3, cp = src; *cp; cnt++, cp++) + if (*cp == '\'') + cnt += 3; + + buf = xmalloc(cnt); + bp = buf; + *bp++ = '\''; + while ((c = *src++)) { + if (c != '\'') + *bp++ = c; + else { + bp = strcpy(bp, "'\\''"); + bp += 4; + } + } + *bp++ = '\''; + *bp = 0; + return buf; +} + diff --git a/quote.h b/quote.h new file mode 100644 index 0000000000..c8cfb3a124 --- /dev/null +++ b/quote.h @@ -0,0 +1,26 @@ +#ifndef QUOTE_H +#define QUOTE_H + + +/* Help to copy the thing properly quoted for the shell safety. + * any single quote is replaced with '\'', and the whole thing + * is enclosed in a single quote pair. + * + * For example, if you are passing the result to system() as an + * argument: + * + * sprintf(cmd, "foobar %s %s", sq_quote(arg0), sq_quote(arg1)) + * + * would be appropriate. If the system() is going to call ssh to + * run the command on the other side: + * + * sprintf(cmd, "git-diff-tree %s %s", sq_quote(arg0), sq_quote(arg1)); + * sprintf(rcmd, "ssh %s %s", sq_quote(host), sq_quote(cmd)); + * + * Note that the above examples leak memory! Remember to free result from + * sq_quote() in a real application. + */ + +char *sq_quote(const char *src); + +#endif |