Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.33-rc4 485 lines 10 kB view raw
1#include "cache.h" 2#include "quote.h" 3 4int quote_path_fully = 1; 5 6/* Help to copy the thing properly quoted for the shell safety. 7 * any single quote is replaced with '\'', any exclamation point 8 * is replaced with '\!', and the whole thing is enclosed in a 9 * 10 * E.g. 11 * original sq_quote result 12 * name ==> name ==> 'name' 13 * a b ==> a b ==> 'a b' 14 * a'b ==> a'\''b ==> 'a'\''b' 15 * a!b ==> a'\!'b ==> 'a'\!'b' 16 */ 17static inline int need_bs_quote(char c) 18{ 19 return (c == '\'' || c == '!'); 20} 21 22void sq_quote_buf(struct strbuf *dst, const char *src) 23{ 24 char *to_free = NULL; 25 26 if (dst->buf == src) 27 to_free = strbuf_detach(dst, NULL); 28 29 strbuf_addch(dst, '\''); 30 while (*src) { 31 size_t len = strcspn(src, "'!"); 32 strbuf_add(dst, src, len); 33 src += len; 34 while (need_bs_quote(*src)) { 35 strbuf_addstr(dst, "'\\"); 36 strbuf_addch(dst, *src++); 37 strbuf_addch(dst, '\''); 38 } 39 } 40 strbuf_addch(dst, '\''); 41 free(to_free); 42} 43 44void sq_quote_print(FILE *stream, const char *src) 45{ 46 char c; 47 48 fputc('\'', stream); 49 while ((c = *src++)) { 50 if (need_bs_quote(c)) { 51 fputs("'\\", stream); 52 fputc(c, stream); 53 fputc('\'', stream); 54 } else { 55 fputc(c, stream); 56 } 57 } 58 fputc('\'', stream); 59} 60 61void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) 62{ 63 int i; 64 65 /* Copy into destination buffer. */ 66 strbuf_grow(dst, 255); 67 for (i = 0; argv[i]; ++i) { 68 strbuf_addch(dst, ' '); 69 sq_quote_buf(dst, argv[i]); 70 if (maxlen && dst->len > maxlen) 71 die("Too many or long arguments"); 72 } 73} 74 75char *sq_dequote_step(char *arg, char **next) 76{ 77 char *dst = arg; 78 char *src = arg; 79 char c; 80 81 if (*src != '\'') 82 return NULL; 83 for (;;) { 84 c = *++src; 85 if (!c) 86 return NULL; 87 if (c != '\'') { 88 *dst++ = c; 89 continue; 90 } 91 /* We stepped out of sq */ 92 switch (*++src) { 93 case '\0': 94 *dst = 0; 95 if (next) 96 *next = NULL; 97 return arg; 98 case '\\': 99 c = *++src; 100 if (need_bs_quote(c) && *++src == '\'') { 101 *dst++ = c; 102 continue; 103 } 104 /* Fallthrough */ 105 default: 106 if (!next || !isspace(*src)) 107 return NULL; 108 do { 109 c = *++src; 110 } while (isspace(c)); 111 *dst = 0; 112 *next = src; 113 return arg; 114 } 115 } 116} 117 118char *sq_dequote(char *arg) 119{ 120 return sq_dequote_step(arg, NULL); 121} 122 123int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc) 124{ 125 char *next = arg; 126 127 if (!*arg) 128 return 0; 129 do { 130 char *dequoted = sq_dequote_step(next, &next); 131 if (!dequoted) 132 return -1; 133 ALLOC_GROW(*argv, *nr + 1, *alloc); 134 (*argv)[(*nr)++] = dequoted; 135 } while (next); 136 137 return 0; 138} 139 140/* 1 means: quote as octal 141 * 0 means: quote as octal if (quote_path_fully) 142 * -1 means: never quote 143 * c: quote as "\\c" 144 */ 145#define X8(x) x, x, x, x, x, x, x, x 146#define X16(x) X8(x), X8(x) 147static signed char const sq_lookup[256] = { 148 /* 0 1 2 3 4 5 6 7 */ 149 /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a', 150 /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1, 151 /* 0x10 */ X16(1), 152 /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1, 153 /* 0x28 */ X16(-1), X16(-1), X16(-1), 154 /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1, 155 /* 0x60 */ X16(-1), X8(-1), 156 /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1, 157 /* 0x80 */ /* set to 0 */ 158}; 159 160static inline int sq_must_quote(char c) 161{ 162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0; 163} 164 165/* 166 * Returns the longest prefix not needing a quote up to maxlen if 167 * positive. 168 * This stops at the first \0 because it's marked as a character 169 * needing an escape. 170 */ 171static ssize_t next_quote_pos(const char *s, ssize_t maxlen) 172{ 173 ssize_t len; 174 175 if (maxlen < 0) { 176 for (len = 0; !sq_must_quote(s[len]); len++); 177 } else { 178 for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++); 179 } 180 return len; 181} 182 183/* 184 * C-style name quoting. 185 * 186 * (1) if sb and fp are both NULL, inspect the input name and counts the 187 * number of bytes that are needed to hold c_style quoted version of name, 188 * counting the double quotes around it but not terminating NUL, and 189 * returns it. 190 * However, if name does not need c_style quoting, it returns 0. 191 * 192 * (2) if sb or fp are not NULL, it emits the c_style quoted version 193 * of name, enclosed with double quotes if asked and needed only. 194 * Return value is the same as in (1). 195 */ 196static size_t quote_c_style_counted(const char *name, ssize_t maxlen, 197 struct strbuf *sb, FILE *fp, int no_dq) 198{ 199#define EMIT(c) \ 200 do { \ 201 if (sb) strbuf_addch(sb, (c)); \ 202 if (fp) fputc((c), fp); \ 203 count++; \ 204 } while (0) 205 206#define EMITBUF(s, l) \ 207 do { \ 208 int __ret; \ 209 if (sb) strbuf_add(sb, (s), (l)); \ 210 if (fp) __ret = fwrite((s), (l), 1, fp); \ 211 count += (l); \ 212 } while (0) 213 214 ssize_t len, count = 0; 215 const char *p = name; 216 217 for (;;) { 218 int ch; 219 220 len = next_quote_pos(p, maxlen); 221 if (len == maxlen || !p[len]) 222 break; 223 224 if (!no_dq && p == name) 225 EMIT('"'); 226 227 EMITBUF(p, len); 228 EMIT('\\'); 229 p += len; 230 ch = (unsigned char)*p++; 231 if (sq_lookup[ch] >= ' ') { 232 EMIT(sq_lookup[ch]); 233 } else { 234 EMIT(((ch >> 6) & 03) + '0'); 235 EMIT(((ch >> 3) & 07) + '0'); 236 EMIT(((ch >> 0) & 07) + '0'); 237 } 238 } 239 240 EMITBUF(p, len); 241 if (p == name) /* no ending quote needed */ 242 return 0; 243 244 if (!no_dq) 245 EMIT('"'); 246 return count; 247} 248 249size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq) 250{ 251 return quote_c_style_counted(name, -1, sb, fp, nodq); 252} 253 254void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq) 255{ 256 if (quote_c_style(prefix, NULL, NULL, 0) || 257 quote_c_style(path, NULL, NULL, 0)) { 258 if (!nodq) 259 strbuf_addch(sb, '"'); 260 quote_c_style(prefix, sb, NULL, 1); 261 quote_c_style(path, sb, NULL, 1); 262 if (!nodq) 263 strbuf_addch(sb, '"'); 264 } else { 265 strbuf_addstr(sb, prefix); 266 strbuf_addstr(sb, path); 267 } 268} 269 270void write_name_quoted(const char *name, FILE *fp, int terminator) 271{ 272 if (terminator) { 273 quote_c_style(name, NULL, fp, 0); 274 } else { 275 fputs(name, fp); 276 } 277 fputc(terminator, fp); 278} 279 280void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, 281 const char *name, FILE *fp, int terminator) 282{ 283 int needquote = 0; 284 285 if (terminator) { 286 needquote = next_quote_pos(pfx, pfxlen) < pfxlen 287 || name[next_quote_pos(name, -1)]; 288 } 289 if (needquote) { 290 fputc('"', fp); 291 quote_c_style_counted(pfx, pfxlen, NULL, fp, 1); 292 quote_c_style(name, NULL, fp, 1); 293 fputc('"', fp); 294 } else { 295 int ret; 296 297 ret = fwrite(pfx, pfxlen, 1, fp); 298 fputs(name, fp); 299 } 300 fputc(terminator, fp); 301} 302 303/* quote path as relative to the given prefix */ 304char *quote_path_relative(const char *in, int len, 305 struct strbuf *out, const char *prefix) 306{ 307 int needquote; 308 309 if (len < 0) 310 len = strlen(in); 311 312 /* "../" prefix itself does not need quoting, but "in" might. */ 313 needquote = (next_quote_pos(in, len) < len); 314 strbuf_setlen(out, 0); 315 strbuf_grow(out, len); 316 317 if (needquote) 318 strbuf_addch(out, '"'); 319 if (prefix) { 320 int off = 0; 321 while (off < len && prefix[off] && prefix[off] == in[off]) 322 if (prefix[off] == '/') { 323 prefix += off + 1; 324 in += off + 1; 325 len -= off + 1; 326 off = 0; 327 } else 328 off++; 329 330 for (; *prefix; prefix++) 331 if (*prefix == '/') 332 strbuf_addstr(out, "../"); 333 } 334 335 quote_c_style_counted (in, len, out, NULL, 1); 336 337 if (needquote) 338 strbuf_addch(out, '"'); 339 if (!out->len) 340 strbuf_addstr(out, "./"); 341 342 return out->buf; 343} 344 345/* 346 * C-style name unquoting. 347 * 348 * Quoted should point at the opening double quote. 349 * + Returns 0 if it was able to unquote the string properly, and appends the 350 * result in the strbuf `sb'. 351 * + Returns -1 in case of error, and doesn't touch the strbuf. Though note 352 * that this function will allocate memory in the strbuf, so calling 353 * strbuf_release is mandatory whichever result unquote_c_style returns. 354 * 355 * Updates endp pointer to point at one past the ending double quote if given. 356 */ 357int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp) 358{ 359 size_t oldlen = sb->len, len; 360 int ch, ac; 361 362 if (*quoted++ != '"') 363 return -1; 364 365 for (;;) { 366 len = strcspn(quoted, "\"\\"); 367 strbuf_add(sb, quoted, len); 368 quoted += len; 369 370 switch (*quoted++) { 371 case '"': 372 if (endp) 373 *endp = quoted; 374 return 0; 375 case '\\': 376 break; 377 default: 378 goto error; 379 } 380 381 switch ((ch = *quoted++)) { 382 case 'a': ch = '\a'; break; 383 case 'b': ch = '\b'; break; 384 case 'f': ch = '\f'; break; 385 case 'n': ch = '\n'; break; 386 case 'r': ch = '\r'; break; 387 case 't': ch = '\t'; break; 388 case 'v': ch = '\v'; break; 389 390 case '\\': case '"': 391 break; /* verbatim */ 392 393 /* octal values with first digit over 4 overflow */ 394 case '0': case '1': case '2': case '3': 395 ac = ((ch - '0') << 6); 396 if ((ch = *quoted++) < '0' || '7' < ch) 397 goto error; 398 ac |= ((ch - '0') << 3); 399 if ((ch = *quoted++) < '0' || '7' < ch) 400 goto error; 401 ac |= (ch - '0'); 402 ch = ac; 403 break; 404 default: 405 goto error; 406 } 407 strbuf_addch(sb, ch); 408 } 409 410 error: 411 strbuf_setlen(sb, oldlen); 412 return -1; 413} 414 415/* quoting as a string literal for other languages */ 416 417void perl_quote_print(FILE *stream, const char *src) 418{ 419 const char sq = '\''; 420 const char bq = '\\'; 421 char c; 422 423 fputc(sq, stream); 424 while ((c = *src++)) { 425 if (c == sq || c == bq) 426 fputc(bq, stream); 427 fputc(c, stream); 428 } 429 fputc(sq, stream); 430} 431 432void python_quote_print(FILE *stream, const char *src) 433{ 434 const char sq = '\''; 435 const char bq = '\\'; 436 const char nl = '\n'; 437 char c; 438 439 fputc(sq, stream); 440 while ((c = *src++)) { 441 if (c == nl) { 442 fputc(bq, stream); 443 fputc('n', stream); 444 continue; 445 } 446 if (c == sq || c == bq) 447 fputc(bq, stream); 448 fputc(c, stream); 449 } 450 fputc(sq, stream); 451} 452 453void tcl_quote_print(FILE *stream, const char *src) 454{ 455 char c; 456 457 fputc('"', stream); 458 while ((c = *src++)) { 459 switch (c) { 460 case '[': case ']': 461 case '{': case '}': 462 case '$': case '\\': case '"': 463 fputc('\\', stream); 464 default: 465 fputc(c, stream); 466 break; 467 case '\f': 468 fputs("\\f", stream); 469 break; 470 case '\r': 471 fputs("\\r", stream); 472 break; 473 case '\n': 474 fputs("\\n", stream); 475 break; 476 case '\t': 477 fputs("\\t", stream); 478 break; 479 case '\v': 480 fputs("\\v", stream); 481 break; 482 } 483 } 484 fputc('"', stream); 485}