Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
sharutils
quoting.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File quoting.diff of Package sharutils
--- configure.ac +++ configure.ac @@ -99,6 +99,7 @@ AM_GNU_GETTEXT AM_GNU_GETTEXT_VERSION([0.14.5]) AM_WITH_DMALLOC +gl_QUOTEARG # sharutils is somewhat special about internationalization in that it # always requires the GNU .mo files installed. --- lib/Makefile.am +++ lib/Makefile.am @@ -26,12 +26,13 @@ CLEANFILES = unlocked-io.h libshar_a_SOURCES = basename.c error.c getopt.c getopt1.c md5.c offtostr.c \ -whoami.c xgetcwd.c xmalloc.c xstrdup.c +whoami.c xgetcwd.c xmalloc.c xstrdup.c quotearg.c xalloc-die.c exitfail.c libshar_a_LIBADD = $(ALLOCA) $(LIBOBJS) noinst_HEADERS = basename.h error.h exit.h getopt.h gettext.h inttostr.h \ -liballoca.h md5.h pathmax.h stpcpy.h system.h xalloc.h xgetcwd.h +liballoca.h md5.h pathmax.h stpcpy.h system.h xalloc.h xgetcwd.h \ +quotearg.h exitfail.h AM_CPPFLAGS = -I.. -I$(srcdir) -I../intl DEFS = -DLIBDIR=\"$(libdir)\" @DEFS@ --- lib/exitfail.c +++ lib/exitfail.c @@ -0,0 +1,27 @@ +/* Failure exit status + + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include "exitfail.h" +#include "exit.h" + +int volatile exit_failure = EXIT_FAILURE; --- lib/exitfail.h +++ lib/exitfail.h @@ -0,0 +1,20 @@ +/* Failure exit status + + Copyright (C) 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +extern int volatile exit_failure; --- lib/quotearg.c +++ lib/quotearg.c @@ -0,0 +1,673 @@ +/* quotearg.c - quote arguments for output + + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert <eggert@twinsun.com> */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include "quotearg.h" + +#include "xalloc.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +#if HAVE_WCHAR_H + +/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared. */ +# include <stdio.h> +# include <time.h> + +# include <wchar.h> +#endif + +#if !HAVE_MBRTOWC +/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the + other macros are defined only for documentation and to satisfy C + syntax. */ +# undef MB_CUR_MAX +# define MB_CUR_MAX 1 +# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0) +# define iswprint(wc) isprint ((unsigned char) (wc)) +# undef HAVE_MBSINIT +#endif + +#if !defined mbsinit && !HAVE_MBSINIT +# define mbsinit(ps) 1 +#endif + +#ifndef iswprint +# if HAVE_WCTYPE_H +# include <wctype.h> +# endif +# if !defined iswprint && !HAVE_ISWPRINT +# define iswprint(wc) 1 +# endif +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#define INT_BITS (sizeof (int) * CHAR_BIT) + +struct quoting_options +{ + /* Basic quoting style. */ + enum quoting_style style; + + /* Quote the characters indicated by this bit vector even if the + quoting style would not normally require them to be quoted. */ + int quote_these_too[(UCHAR_MAX / INT_BITS) + 1]; +}; + +/* Names of quoting styles. */ +char const *const quoting_style_args[] = +{ + "literal", + "shell", + "shell-always", + "c", + "escape", + "locale", + "clocale", + 0 +}; + +/* Correspondences to quoting style names. */ +enum quoting_style const quoting_style_vals[] = +{ + literal_quoting_style, + shell_quoting_style, + shell_always_quoting_style, + c_quoting_style, + escape_quoting_style, + locale_quoting_style, + clocale_quoting_style +}; + +/* The default quoting options. */ +static struct quoting_options default_quoting_options; + +/* Allocate a new set of quoting options, with contents initially identical + to O if O is not null, or to the default if O is null. + It is the caller's responsibility to free the result. */ +struct quoting_options * +clone_quoting_options (struct quoting_options *o) +{ + int e = errno; + struct quoting_options *p = xmalloc (sizeof *p); + *p = *(o ? o : &default_quoting_options); + errno = e; + return p; +} + +/* Get the value of O's quoting style. If O is null, use the default. */ +enum quoting_style +get_quoting_style (struct quoting_options *o) +{ + return (o ? o : &default_quoting_options)->style; +} + +/* In O (or in the default if O is null), + set the value of the quoting style to S. */ +void +set_quoting_style (struct quoting_options *o, enum quoting_style s) +{ + (o ? o : &default_quoting_options)->style = s; +} + +/* In O (or in the default if O is null), + set the value of the quoting options for character C to I. + Return the old value. Currently, the only values defined for I are + 0 (the default) and 1 (which means to quote the character even if + it would not otherwise be quoted). */ +int +set_char_quoting (struct quoting_options *o, char c, int i) +{ + unsigned char uc = c; + int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS; + int shift = uc % INT_BITS; + int r = (*p >> shift) & 1; + *p ^= ((i & 1) ^ r) << shift; + return r; +} + +/* MSGID approximates a quotation mark. Return its translation if it + has one; otherwise, return either it or "\"", depending on S. */ +static char const * +gettext_quote (char const *msgid, enum quoting_style s) +{ + char const *translation = _(msgid); + if (translation == msgid && s == clocale_quoting_style) + translation = "\""; + return translation; +} + +/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of + argument ARG (of size ARGSIZE), using QUOTING_STYLE and the + non-quoting-style part of O to control quoting. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFFERSIZE is too small to store the output string, return the + value that would have been returned had BUFFERSIZE been large enough. + If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE. + + This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG, + ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting + style specified by O, and O may not be null. */ + +static size_t +quotearg_buffer_restyled (char *buffer, size_t buffersize, + char const *arg, size_t argsize, + enum quoting_style quoting_style, + struct quoting_options const *o) +{ + size_t i; + size_t len = 0; + char const *quote_string = 0; + size_t quote_string_len = 0; + bool backslash_escapes = false; + bool unibyte_locale = MB_CUR_MAX == 1; + +#define STORE(c) \ + do \ + { \ + if (len < buffersize) \ + buffer[len] = (c); \ + len++; \ + } \ + while (0) + + switch (quoting_style) + { + case c_quoting_style: + STORE ('"'); + backslash_escapes = true; + quote_string = "\""; + quote_string_len = 1; + break; + + case escape_quoting_style: + backslash_escapes = true; + break; + + case locale_quoting_style: + case clocale_quoting_style: + { + /* Get translations for open and closing quotation marks. + + The message catalog should translate "`" to a left + quotation mark suitable for the locale, and similarly for + "'". If the catalog has no translation, + locale_quoting_style quotes `like this', and + clocale_quoting_style quotes "like this". + + For example, an American English Unicode locale should + translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and + should translate "'" to U+201D (RIGHT DOUBLE QUOTATION + MARK). A British English Unicode locale should instead + translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and + U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. */ + + char const *left = gettext_quote (N_("`"), quoting_style); + char const *right = gettext_quote (N_("'"), quoting_style); + for (quote_string = left; *quote_string; quote_string++) + STORE (*quote_string); + backslash_escapes = true; + quote_string = right; + quote_string_len = strlen (quote_string); + } + break; + + case shell_always_quoting_style: + STORE ('\''); + quote_string = "'"; + quote_string_len = 1; + break; + + default: + break; + } + + for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++) + { + unsigned char c; + unsigned char esc; + + if (backslash_escapes + && quote_string_len + && i + quote_string_len <= argsize + && memcmp (arg + i, quote_string, quote_string_len) == 0) + STORE ('\\'); + + c = arg[i]; + switch (c) + { + case '\0': + if (backslash_escapes) + { + STORE ('\\'); + STORE ('0'); + STORE ('0'); + c = '0'; + } + break; + + case '?': + switch (quoting_style) + { + case shell_quoting_style: + goto use_shell_always_quoting_style; + + case c_quoting_style: + if (i + 2 < argsize && arg[i + 1] == '?') + switch (arg[i + 2]) + { + case '!': case '\'': + case '(': case ')': case '-': case '/': + case '<': case '=': case '>': + /* Escape the second '?' in what would otherwise be + a trigraph. */ + c = arg[i + 2]; + i += 2; + STORE ('?'); + STORE ('\\'); + STORE ('?'); + break; + } + break; + + default: + break; + } + break; + + case '\a': esc = 'a'; goto c_escape; + case '\b': esc = 'b'; goto c_escape; + case '\f': esc = 'f'; goto c_escape; + case '\n': esc = 'n'; goto c_and_shell_escape; + case '\r': esc = 'r'; goto c_and_shell_escape; + case '\t': esc = 't'; goto c_and_shell_escape; + case '\v': esc = 'v'; goto c_escape; + case '\\': esc = c; goto c_and_shell_escape; + + c_and_shell_escape: + if (quoting_style == shell_quoting_style) + goto use_shell_always_quoting_style; + c_escape: + if (backslash_escapes) + { + c = esc; + goto store_escape; + } + break; + + case '{': case '}': /* sometimes special if isolated */ + if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1)) + break; + /* Fall through. */ + case '#': case '~': + if (i != 0) + break; + /* Fall through. */ + case ' ': + case '!': /* special in bash */ + case '"': case '$': case '&': + case '(': case ')': case '*': case ';': + case '<': + case '=': /* sometimes special in 0th or (with "set -k") later args */ + case '>': case '[': + case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */ + case '`': case '|': + /* A shell special character. In theory, '$' and '`' could + be the first bytes of multibyte characters, which means + we should check them with mbrtowc, but in practice this + doesn't happen so it's not worth worrying about. */ + if (quoting_style == shell_quoting_style) + goto use_shell_always_quoting_style; + break; + + case '\'': + switch (quoting_style) + { + case shell_quoting_style: + goto use_shell_always_quoting_style; + + case shell_always_quoting_style: + STORE ('\''); + STORE ('\\'); + STORE ('\''); + break; + + default: + break; + } + break; + + case '%': case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': case ':': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': case ']': case '_': case 'a': case 'b': + case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': + case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + /* These characters don't cause problems, no matter what the + quoting style is. They cannot start multibyte sequences. */ + break; + + default: + /* If we have a multibyte sequence, copy it until we reach + its end, find an error, or come back to the initial shift + state. For C-like styles, if the sequence has + unprintable characters, escape the whole sequence, since + we can't easily escape single characters within it. */ + { + /* Length of multibyte sequence found so far. */ + size_t m; + + bool printable; + + if (unibyte_locale) + { + m = 1; + printable = isprint (c) != 0; + } + else + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + + m = 0; + printable = true; + if (argsize == SIZE_MAX) + argsize = strlen (arg); + + do + { + wchar_t w; + size_t bytes = mbrtowc (&w, &arg[i + m], + argsize - (i + m), &mbstate); + if (bytes == 0) + break; + else if (bytes == (size_t) -1) + { + printable = false; + break; + } + else if (bytes == (size_t) -2) + { + printable = false; + while (i + m < argsize && arg[i + m]) + m++; + break; + } + else + { + /* Work around a bug with older shells that "see" a '\' + that is really the 2nd byte of a multibyte character. + In practice the problem is limited to ASCII + chars >= '@' that are shell special chars. */ + if ('[' == 0x5b && quoting_style == shell_quoting_style) + { + size_t j; + for (j = 1; j < bytes; j++) + switch (arg[i + m + j]) + { + case '[': case '\\': case '^': + case '`': case '|': + goto use_shell_always_quoting_style; + } + } + + if (! iswprint (w)) + printable = false; + m += bytes; + } + } + while (! mbsinit (&mbstate)); + } + + if (1 < m || (backslash_escapes && ! printable)) + { + /* Output a multibyte sequence, or an escaped + unprintable unibyte character. */ + size_t ilim = i + m; + + for (;;) + { + if (backslash_escapes && ! printable) + { + STORE ('\\'); + STORE ('0' + (c >> 6)); + STORE ('0' + ((c >> 3) & 7)); + c = '0' + (c & 7); + } + if (ilim <= i + 1) + break; + STORE (c); + c = arg[++i]; + } + + goto store_c; + } + } + } + + if (! (backslash_escapes + && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))) + goto store_c; + + store_escape: + STORE ('\\'); + + store_c: + STORE (c); + } + + if (i == 0 && quoting_style == shell_quoting_style) + goto use_shell_always_quoting_style; + + if (quote_string) + for (; *quote_string; quote_string++) + STORE (*quote_string); + + if (len < buffersize) + buffer[len] = '\0'; + return len; + + use_shell_always_quoting_style: + return quotearg_buffer_restyled (buffer, buffersize, arg, argsize, + shell_always_quoting_style, o); +} + +/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of + argument ARG (of size ARGSIZE), using O to control quoting. + If O is null, use the default. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFFERSIZE is too small to store the output string, return the + value that would have been returned had BUFFERSIZE been large enough. + If ARGSIZE is SIZE_MAX, use the string length of the argument for + ARGSIZE. */ +size_t +quotearg_buffer (char *buffer, size_t buffersize, + char const *arg, size_t argsize, + struct quoting_options const *o) +{ + struct quoting_options const *p = o ? o : &default_quoting_options; + int e = errno; + size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize, + p->style, p); + errno = e; + return r; +} + +/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly + allocated storage containing the quoted string. */ +char * +quotearg_alloc (char const *arg, size_t argsize, + struct quoting_options const *o) +{ + int e = errno; + size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1; + char *buf = xmalloc (bufsize); + quotearg_buffer (buf, bufsize, arg, argsize, o); + errno = e; + return buf; +} + +/* Use storage slot N to return a quoted version of argument ARG. + ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a + null-terminated string. + OPTIONS specifies the quoting options. + The returned value points to static storage that can be + reused by the next call to this function with the same value of N. + N must be nonnegative. N is deliberately declared with type "int" + to allow for future extensions (using negative values). */ +static char * +quotearg_n_options (int n, char const *arg, size_t argsize, + struct quoting_options const *options) +{ + int e = errno; + + /* Preallocate a slot 0 buffer, so that the caller can always quote + one small component of a "memory exhausted" message in slot 0. */ + static char slot0[256]; + static unsigned int nslots = 1; + unsigned int n0 = n; + struct slotvec + { + size_t size; + char *val; + }; + static struct slotvec slotvec0 = {sizeof slot0, slot0}; + static struct slotvec *slotvec = &slotvec0; + + if (n < 0) + abort (); + + if (nslots <= n0) + { + unsigned int n1 = n0 + 1; + + if (xalloc_oversized (n1, sizeof *slotvec)) + xalloc_die (); + + if (slotvec == &slotvec0) + { + slotvec = xmalloc (sizeof *slotvec); + *slotvec = slotvec0; + } + slotvec = xrealloc (slotvec, n1 * sizeof *slotvec); + memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec); + nslots = n1; + } + + { + size_t size = slotvec[n].size; + char *val = slotvec[n].val; + size_t qsize = quotearg_buffer (val, size, arg, argsize, options); + + if (size <= qsize) + { + slotvec[n].size = size = qsize + 1; + if (val != slot0) + free (val); + slotvec[n].val = val = xmalloc (size); + quotearg_buffer (val, size, arg, argsize, options); + } + + errno = e; + return val; + } +} + +char * +quotearg_n (int n, char const *arg) +{ + return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options); +} + +char * +quotearg (char const *arg) +{ + return quotearg_n (0, arg); +} + +/* Return quoting options for STYLE, with no extra quoting. */ +static struct quoting_options +quoting_options_from_style (enum quoting_style style) +{ + struct quoting_options o; + o.style = style; + memset (o.quote_these_too, 0, sizeof o.quote_these_too); + return o; +} + +char * +quotearg_n_style (int n, enum quoting_style s, char const *arg) +{ + struct quoting_options const o = quoting_options_from_style (s); + return quotearg_n_options (n, arg, SIZE_MAX, &o); +} + +char * +quotearg_n_style_mem (int n, enum quoting_style s, + char const *arg, size_t argsize) +{ + struct quoting_options const o = quoting_options_from_style (s); + return quotearg_n_options (n, arg, argsize, &o); +} + +char * +quotearg_style (enum quoting_style s, char const *arg) +{ + return quotearg_n_style (0, s, arg); +} + +char * +quotearg_char (char const *arg, char ch) +{ + struct quoting_options options; + options = default_quoting_options; + set_char_quoting (&options, ch, 1); + return quotearg_n_options (0, arg, SIZE_MAX, &options); +} + +char * +quotearg_colon (char const *arg) +{ + return quotearg_char (arg, ':'); +} --- lib/quotearg.h +++ lib/quotearg.h @@ -0,0 +1,137 @@ +/* quotearg.h - quote arguments for output + + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert <eggert@twinsun.com> */ + +#ifndef QUOTEARG_H_ +# define QUOTEARG_H_ 1 + +# include <stddef.h> + +/* Basic quoting styles. */ +enum quoting_style + { + /* Output names as-is (ls --quoting-style=literal). */ + literal_quoting_style, + + /* Quote names for the shell if they contain shell metacharacters + or would cause ambiguous output (ls --quoting-style=shell). */ + shell_quoting_style, + + /* Quote names for the shell, even if they would normally not + require quoting (ls --quoting-style=shell-always). */ + shell_always_quoting_style, + + /* Quote names as for a C language string (ls --quoting-style=c). */ + c_quoting_style, + + /* Like c_quoting_style except omit the surrounding double-quote + characters (ls --quoting-style=escape). */ + escape_quoting_style, + + /* Like clocale_quoting_style, but quote `like this' instead of + "like this" in the default C locale (ls --quoting-style=locale). */ + locale_quoting_style, + + /* Like c_quoting_style except use quotation marks appropriate for + the locale (ls --quoting-style=clocale). */ + clocale_quoting_style + }; + +/* For now, --quoting-style=literal is the default, but this may change. */ +# ifndef DEFAULT_QUOTING_STYLE +# define DEFAULT_QUOTING_STYLE literal_quoting_style +# endif + +/* Names of quoting styles and their corresponding values. */ +extern char const *const quoting_style_args[]; +extern enum quoting_style const quoting_style_vals[]; + +struct quoting_options; + +/* The functions listed below set and use a hidden variable + that contains the default quoting style options. */ + +/* Allocate a new set of quoting options, with contents initially identical + to O if O is not null, or to the default if O is null. + It is the caller's responsibility to free the result. */ +struct quoting_options *clone_quoting_options (struct quoting_options *o); + +/* Get the value of O's quoting style. If O is null, use the default. */ +enum quoting_style get_quoting_style (struct quoting_options *o); + +/* In O (or in the default if O is null), + set the value of the quoting style to S. */ +void set_quoting_style (struct quoting_options *o, enum quoting_style s); + +/* In O (or in the default if O is null), + set the value of the quoting options for character C to I. + Return the old value. Currently, the only values defined for I are + 0 (the default) and 1 (which means to quote the character even if + it would not otherwise be quoted). */ +int set_char_quoting (struct quoting_options *o, char c, int i); + +/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of + argument ARG (of size ARGSIZE), using O to control quoting. + If O is null, use the default. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFFERSIZE is too small to store the output string, return the + value that would have been returned had BUFFERSIZE been large enough. + If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */ +size_t quotearg_buffer (char *buffer, size_t buffersize, + char const *arg, size_t argsize, + struct quoting_options const *o); + +/* Like quotearg_buffer, except return the result in a newly allocated + buffer. It is the caller's responsibility to free the result. */ +char *quotearg_alloc (char const *arg, size_t argsize, + struct quoting_options const *o); + +/* Use storage slot N to return a quoted version of the string ARG. + Use the default quoting options. + The returned value points to static storage that can be + reused by the next call to this function with the same value of N. + N must be nonnegative. */ +char *quotearg_n (int n, char const *arg); + +/* Equivalent to quotearg_n (0, ARG). */ +char *quotearg (char const *arg); + +/* Use style S and storage slot N to return a quoted version of the string ARG. + This is like quotearg_n (N, ARG), except that it uses S with no other + options to specify the quoting method. */ +char *quotearg_n_style (int n, enum quoting_style s, char const *arg); + +/* Use style S and storage slot N to return a quoted version of the + argument ARG of size ARGSIZE. This is like quotearg_n_style + (N, S, ARG), except it can quote null bytes. */ +char *quotearg_n_style_mem (int n, enum quoting_style s, + char const *arg, size_t argsize); + +/* Equivalent to quotearg_n_style (0, S, ARG). */ +char *quotearg_style (enum quoting_style s, char const *arg); + +/* Like quotearg (ARG), except also quote any instances of CH. */ +char *quotearg_char (char const *arg, char ch); + +/* Equivalent to quotearg_char (ARG, ':'). */ +char *quotearg_colon (char const *arg); + +#endif /* !QUOTEARG_H_ */ --- lib/xalloc-die.c +++ lib/xalloc-die.c @@ -0,0 +1,45 @@ +/* Report a memory allocation failure and exit. + + Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 Free + Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include "xalloc.h" + +#include <stdlib.h> + +#include "error.h" +#include "exitfail.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +void +xalloc_die (void) +{ + error (exit_failure, 0, "%s", _("memory exhausted")); + + /* The `noreturn' cannot be given to error, since it may return if + its first argument is 0. To help compilers understand the + xalloc_die does not return, call abort. Also, the abort is a + safety feature if exit_failure is 0 (which shouldn't happen). */ + abort (); +} --- lib/xalloc.h +++ lib/xalloc.h @@ -1,5 +1,7 @@ /* xalloc.h -- malloc with out-of-memory checking - Copyright (C) 1990-1998, 1999, 2000 Free Software Foundation, Inc. + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,14 +20,14 @@ #ifndef XALLOC_H_ # define XALLOC_H_ -# ifndef PARAMS -# if defined PROTOTYPES || (defined __STDC__ && __STDC__) -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif +# include <stddef.h> + + +# ifdef __cplusplus +extern "C" { # endif + # ifndef __attribute__ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ # define __attribute__(x) @@ -36,52 +38,42 @@ # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) # endif -/* Exit value when the requested amount of memory is not available. - It is initialized to EXIT_FAILURE, but the caller may set it to - some other value. */ -extern int xalloc_exit_failure; - -/* If this pointer is non-zero, run the specified function upon each - allocation failure. It is initialized to zero. */ -extern void (*xalloc_fail_func) PARAMS ((void)); - -/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this - message is output. It is translated via gettext. - Its value is "memory exhausted". */ -extern char const xalloc_msg_memory_exhausted[]; - -/* This function is always triggered when memory is exhausted. It is - in charge of honoring the three previous items. This is the +/* This function is always triggered when memory is exhausted. + It must be defined by the application, either explicitly + or by using gnulib's xalloc-die module. This is the function to call when one wants the program to die because of a memory allocation failure. */ -extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN; +extern void xalloc_die (void) ATTRIBUTE_NORETURN; -void *xmalloc PARAMS ((size_t n)); -void *xcalloc PARAMS ((size_t n, size_t s)); -void *xrealloc PARAMS ((void *p, size_t n)); -char *xstrdup PARAMS ((const char *str)); - -# define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items))) -# define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items))) -# define XREALLOC(Ptr, Type, N_items) \ - ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items))) - -/* Declare and alloc memory for VAR of type TYPE. */ -# define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1) - -/* Free VAR only if non NULL. */ -# define XFREE(Var) \ - do { \ - if (Var) \ - free (Var); \ - } while (0) - -/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */ -# define CCLONE(Src, Num) \ - (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num))) +void *xmalloc (size_t s); +void *xnmalloc (size_t n, size_t s); +void *xzalloc (size_t s); +void *xcalloc (size_t n, size_t s); +void *xrealloc (void *p, size_t s); +void *xnrealloc (void *p, size_t n, size_t s); +void *x2realloc (void *p, size_t *pn); +void *x2nrealloc (void *p, size_t *pn, size_t s); +void *xmemdup (void const *p, size_t s); +char *xstrdup (char const *str); + +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) -/* Return a malloc'ed copy of SRC. */ -# define CLONE(Src) CCLONE (Src, 1) +# ifdef __cplusplus +} +# endif #endif /* !XALLOC_H_ */ --- lib/xmalloc.c +++ lib/xmalloc.c @@ -1,5 +1,7 @@ /* xmalloc.c -- malloc with out of memory checking - Copyright (C) 1990-1999, 2000 Free Software Foundation, Inc. + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,62 +21,31 @@ # include <config.h> #endif -#include <sys/types.h> - -#if STDC_HEADERS -# include <stdlib.h> -#else -void *calloc (); -void *malloc (); -void *realloc (); -void free (); -#endif - -#if ENABLE_NLS -# include <libintl.h> -# define _(Text) gettext (Text) -#else -# define textdomain(Domain) -# define _(Text) Text -#endif -#define N_(Text) Text - -#include "error.h" #include "xalloc.h" -#ifndef EXIT_FAILURE -# define EXIT_FAILURE 1 -#endif +#include <stdlib.h> +#include <string.h> -#ifndef HAVE_DONE_WORKING_MALLOC_CHECK -"you must run the autoconf test for a properly working malloc -- see malloc.m4" +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) #endif -#ifndef HAVE_DONE_WORKING_REALLOC_CHECK -"you must run the autoconf test for a properly working realloc --see realloc.m4" -#endif +/* Allocate an array of N objects, each with S bytes of memory, + dynamically, with error checking. S must be nonzero. */ -/* Exit value when the requested amount of memory is not available. - The caller may set it to some other value. */ -int xalloc_exit_failure = EXIT_FAILURE; - -/* If non NULL, call this function when memory is exhausted. */ -void (*xalloc_fail_func) PARAMS ((void)) = 0; - -/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message - before exiting when memory is exhausted. Goes through gettext. */ -char const xalloc_msg_memory_exhausted[] = N_("memory exhausted"); - -void -xalloc_die (void) -{ - if (xalloc_fail_func) - (*xalloc_fail_func) (); - error (xalloc_exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted)); - /* The `noreturn' cannot be given to error, since it may return if - its first argument is 0. To help compilers understand the - xalloc_die does terminate, call exit. */ - exit (EXIT_FAILURE); +static inline void * +xnmalloc_inline (size_t n, size_t s) +{ + void *p; + if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0)) + xalloc_die (); + return p; +} + +void * +xnmalloc (size_t n, size_t s) +{ + return xnmalloc_inline (n, s); } /* Allocate N bytes of memory dynamically, with error checking. */ @@ -82,35 +53,169 @@ void * xmalloc (size_t n) { - void *p; + return xnmalloc_inline (n, 1); +} - p = malloc (n); - if (p == 0) +/* Change the size of an allocated block of memory P to an array of N + objects each of S bytes, with error checking. S must be nonzero. */ + +static inline void * +xnrealloc_inline (void *p, size_t n, size_t s) +{ + if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0)) xalloc_die (); return p; } +void * +xnrealloc (void *p, size_t n, size_t s) +{ + return xnrealloc_inline (p, n, s); +} + /* Change the size of an allocated block of memory P to N bytes, with error checking. */ void * xrealloc (void *p, size_t n) { - p = realloc (p, n); - if (p == 0) - xalloc_die (); - return p; + return xnrealloc_inline (p, n, 1); +} + + +/* If P is null, allocate a block of at least *PN such objects; + otherwise, reallocate P so that it contains more than *PN objects + each of S bytes. *PN must be nonzero unless P is null, and S must + be nonzero. Set *PN to the new number of objects, and return the + pointer to the new block. *PN is never set to zero, and the + returned pointer is never null. + + Repeated reallocations are guaranteed to make progress, either by + allocating an initial block with a nonzero size, or by allocating a + larger block. + + In the following implementation, nonzero sizes are doubled so that + repeated reallocations have O(N log N) overall cost rather than + O(N**2) cost, but the specification for this function does not + guarantee that sizes are doubled. + + Here is an example of use: + + int *p = NULL; + size_t used = 0; + size_t allocated = 0; + + void + append_int (int value) + { + if (used == allocated) + p = x2nrealloc (p, &allocated, sizeof *p); + p[used++] = value; + } + + This causes x2nrealloc to allocate a block of some nonzero size the + first time it is called. + + To have finer-grained control over the initial size, set *PN to a + nonzero value before calling this function with P == NULL. For + example: + + int *p = NULL; + size_t used = 0; + size_t allocated = 0; + size_t allocated1 = 1000; + + void + append_int (int value) + { + if (used == allocated) + { + p = x2nrealloc (p, &allocated1, sizeof *p); + allocated = allocated1; + } + p[used++] = value; + } + + */ + +static inline void * +x2nrealloc_inline (void *p, size_t *pn, size_t s) +{ + size_t n = *pn; + + if (! p) + { + if (! n) + { + /* The approximate size to use for initial small allocation + requests, when the invoking code specifies an old size of + zero. 64 bytes is the largest "small" request for the + GNU C library malloc. */ + enum { DEFAULT_MXFAST = 64 }; + + n = DEFAULT_MXFAST / s; + n += !n; + } + } + else + { + if (SIZE_MAX / 2 / s < n) + xalloc_die (); + n *= 2; + } + + *pn = n; + return xrealloc (p, n * s); } -/* Allocate memory for N elements of S bytes, with error checking. */ +void * +x2nrealloc (void *p, size_t *pn, size_t s) +{ + return x2nrealloc_inline (p, pn, s); +} + +/* If P is null, allocate a block of at least *PN bytes; otherwise, + reallocate P so that it contains more than *PN bytes. *PN must be + nonzero unless P is null. Set *PN to the new block's size, and + return the pointer to the new block. *PN is never set to zero, and + the returned pointer is never null. */ + +void * +x2realloc (void *p, size_t *pn) +{ + return x2nrealloc_inline (p, pn, 1); +} + +/* Allocate S bytes of zeroed memory dynamically, with error checking. + There's no need for xnzalloc (N, S), since it would be equivalent + to xcalloc (N, S). */ + +void * +xzalloc (size_t s) +{ + return memset (xmalloc (s), 0, s); +} + +/* Allocate zeroed memory for N elements of S bytes, with error + checking. S must be nonzero. */ void * xcalloc (size_t n, size_t s) { void *p; - - p = calloc (n, s); - if (p == 0) + /* Test for overflow, since some calloc implementations don't have + proper overflow checks. */ + if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0)) xalloc_die (); return p; } + +/* Clone an object P of size S, with error checking. There's no need + for xnclone (P, N, S), since xclone (P, N * S) works without any + need for an arithmetic overflow check. */ + +void * +xclone (void const *p, size_t s) +{ + return memcpy (xmalloc (s), p, s); +} --- m4/quotearg.m4 +++ m4/quotearg.m4 @@ -0,0 +1,16 @@ +# quotearg.m4 serial 2 +dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +AC_DEFUN([gl_QUOTEARG], +[ + dnl Prerequisites of lib/quotearg.c. + AC_CHECK_HEADERS(wchar.h wctype.h) + AC_CHECK_FUNCS(iswprint mbsinit) + AC_TYPE_MBSTATE_T + AC_FUNC_MBRTOWC +]) --- src/scripts.def +++ src/scripts.def @@ -159,7 +159,7 @@ body = <<- _EOBody_ if ${md5check} then ( - ${MD5SUM} -c >/dev/null 2>&1 || ${echo} '%s: %s' + ${MD5SUM} -c >/dev/null 2>&1 || ${echo} %s: '%s' ) << %s _EOBody_; }; --- src/scripts.x +++ src/scripts.x @@ -131,7 +131,7 @@ #line 160 "scripts.def" " if ${md5check}\n\ then (\n\ - ${MD5SUM} -c >/dev/null 2>&1 || ${echo} '%s: %s'\n\ + ${MD5SUM} -c >/dev/null 2>&1 || ${echo} %s: '%s'\n\ ) << %s\n"; static const char query_answers_z[769] = --- src/shar.c +++ src/shar.c @@ -147,6 +147,7 @@ #include "getopt.h" #include "inttostr.h" #include "md5.h" +#include "quotearg.h" /* No Brown-Shirt mode. */ static int vanilla_operation_mode = 0; @@ -698,6 +699,8 @@ generate_mkdir (path) const char *path; { + char *quoted_path = quotearg_n_style (2, shell_always_quoting_style, path); + /* If already generated code for this dir creation, don't do again. */ { @@ -738,18 +741,18 @@ /* Generate the text. */ - fprintf (output, "if test ! -d '%s'; then\n", path); + fprintf (output, "if test ! -d %s; then\n", quoted_path); if (!quiet_unshar_mode) { const char* did_pz = - N_("x - created directory `%s'\\''."); + N_("x - created directory `'%s\\''."); const char* not_pz = - N_("x - failed to create directory `%s'\\''."); - fprintf (output, " mkdir '%s'\n", path); - echo_status ("test $? -eq 0", did_pz, not_pz, path, 1); + N_("x - failed to create directory `'%s\\''."); + fprintf (output, " mkdir %s\n", quoted_path); + echo_status ("test $? -eq 0", did_pz, not_pz, quoted_path, 1); } else - fprintf (output, " mkdir '%s' || exit 1\n", path); + fprintf (output, " mkdir %s || exit 1\n", quoted_path); fputs ("fi\n", output); } @@ -988,7 +991,7 @@ failed. */ fputs (" :\n", output); - echo_status ("test $? -ne 0", N_("restore of %s failed"), NULL, + echo_status ("test $? -ne 0", N_("restore of '%s' failed"), NULL, restore_name, 0); fputs ("'\n${echo} '", output); @@ -1052,6 +1055,7 @@ const char *file_type; /* text of binary */ const char *file_type_remote; /* text or binary, avoiding locale */ struct tm *restore_time; + const char *quoted_local_name, *quoted_restore_name; /* Check to see that this is still a regular file and readable. */ @@ -1066,6 +1070,11 @@ return 1; } + quoted_local_name = quotearg_n_style (0, shell_always_quoting_style, + local_name); + quoted_restore_name = quotearg_n_style (1, shell_always_quoting_style, + restore_name); + /* If file_size_limit set, get the current output length. */ if (file_size_limit) @@ -1079,7 +1088,7 @@ ? struct_stat.st_size + struct_stat.st_size / 3 : struct_stat.st_size) > remaining_size)) - change_files (restore_name, remaining_size); + change_files (quoted_restore_name, remaining_size); } else remaining_size = 0; /* give some value to the variable */ @@ -1188,23 +1197,24 @@ /* Start writing the pipe with encodes. */ FILE *outptr; + char *cmdline = alloca (strlen (quoted_local_name) + 100); if (compressed_file_mode) { - sprintf (buffer, "compress -b%d < '%s'", - bits_per_compressed_byte, local_name); - input = popen (buffer, "r"); + sprintf (cmdline, "compress -b%d < %s", + bits_per_compressed_byte, quoted_local_name); + input = popen (cmdline, "r"); } else if (gzipped_file_mode) { - sprintf (buffer, "gzip -%d < '%s'", - gzip_compression_level, local_name); - input = popen (buffer, "r"); + sprintf (cmdline, "gzip -%d < %s", + gzip_compression_level, quoted_local_name); + input = popen (cmdline, "r"); } else if (bzipped_file_mode) { - sprintf (buffer, "bzip2 < '%s'", local_name); - input = popen (buffer, "r"); + sprintf (cmdline, "bzip2 < %s", quoted_local_name); + input = popen (cmdline, "r"); } else input = fopen (local_name, "rb"); @@ -1248,27 +1258,27 @@ if (check_existing_mode) { - fprintf (output, "if test -f '%s' && test \"$first_param\" != -c; then\n", - restore_name); + fprintf (output, "if test -f %s && test \"$first_param\" != -c; then\n", + quoted_restore_name); if (query_user_mode) { char* pzOverwriting = scribble; char* pzOverwrite; - sprintf (pzOverwriting, N_("overwriting %s"), restore_name); + sprintf (pzOverwriting, N_("overwriting '%s'"), quoted_restore_name); pzOverwrite = scribble + strlen(pzOverwriting) + 2; - sprintf (pzOverwrite, N_("overwrite %s"), restore_name); + sprintf (pzOverwrite, N_("overwrite '%s'"), quoted_restore_name); fprintf (output, query_user_z, pzOverwriting, pzOverwrite); - sprintf (pzOverwriting, N_("SKIPPING %s"), restore_name); + sprintf (pzOverwriting, N_("SKIPPING '%s'"), quoted_restore_name); fprintf (output, query_check_z, N_("extraction aborted"), pzOverwriting, pzOverwriting); } else - echo_text (N_("SKIPPING %s (file already exists)"), - restore_name, 0); + echo_text (N_("SKIPPING '%s' (file already exists)"), + quoted_restore_name, 0); if (split_file_mode) fputs (" rm -f ${lock_dir}/new\nelse\n > ${lock_dir}/new\n", output); @@ -1281,8 +1291,8 @@ if (!quiet_unshar_mode) { - sprintf (scribble, N_("x - extracting %s %s"), - restore_name, file_type_remote); + sprintf (scribble, N_("x - extracting '%s' %s"), + quoted_restore_name, file_type_remote); fprintf (output, echo_string_z, scribble); } @@ -1291,8 +1301,8 @@ /* Just touch the file, or empty it if it exists. */ - fprintf (output, " > '%s' &&\n", - restore_name); + fprintf (output, " > %s &&\n", + quoted_restore_name); } else { @@ -1315,8 +1325,8 @@ /* Just run it into the file. */ - fprintf (output, " sed 's/^%c//' << '%s' > '%s' &&\n", - line_prefix, here_delimiter, restore_name); + fprintf (output, " sed 's/^%c//' << '%s' > %s &&\n", + line_prefix, here_delimiter, quoted_restore_name); } while (fgets (buffer, BUFSIZ, input)) @@ -1397,8 +1407,8 @@ failed. */ fputs (" :\n", output); - echo_status ("test $? -ne 0", N_("restore of %s failed\n"), NULL, - restore_name, 0); + echo_status ("test $? -ne 0", N_("restore of '%s' failed\n"), NULL, + quoted_restore_name, 0); if (check_existing_mode) fputs ("fi\n", output); @@ -1521,24 +1531,24 @@ if (!quiet_unshar_mode) echo_text (N_("uncompressing file %s"), restore_name, 1); - fprintf (output, " compress -d < ${lock_dir}/cmp > '%s' &&\n", - restore_name); + fprintf (output, " compress -d < ${lock_dir}/cmp > %s &&\n", + quoted_restore_name); } else if (gzipped_file_mode) { if (!quiet_unshar_mode) echo_text (N_("gunzipping file %s"), restore_name, 1); - fprintf (output, " gzip -d < ${lock_dir}/gzi > '%s' &&\n", - restore_name); + fprintf (output, " gzip -d < ${lock_dir}/gzi > %s &&\n", + quoted_restore_name); } else if (bzipped_file_mode) { if (!quiet_unshar_mode) echo_text (N_("bunzipping file %s"), restore_name, 1); - fprintf (output, " bzip2 -d < ${lock_dir}/bzi > '%s' &&\n", - restore_name); + fprintf (output, " bzip2 -d < ${lock_dir}/bzi > %s &&\n", + quoted_restore_name); } } @@ -1549,12 +1559,12 @@ restore_time = localtime (&struct_stat.st_mtime); fprintf (output, "\ - (set %02d %02d %02d %02d %02d %02d %02d '%s'; eval \"$shar_touch\") &&\n", + (set %02d %02d %02d %02d %02d %02d %02d %s; eval \"$shar_touch\") &&\n", (restore_time->tm_year + 1900) / 100, (restore_time->tm_year + 1900) % 100, restore_time->tm_mon + 1, restore_time->tm_mday, restore_time->tm_hour, restore_time->tm_min, - restore_time->tm_sec, restore_name); + restore_time->tm_sec, quoted_restore_name); } if (vanilla_operation_mode) @@ -1563,8 +1573,8 @@ /* Close the "&&" and report an error if any of the above failed. */ fputs (":\n", output); - echo_status ("test $? -ne 0", N_("restore of %s failed"), NULL, - restore_name, 0); + echo_status ("test $? -ne 0", N_("restore of '%s' failed"), NULL, + quoted_restore_name, 0); } else { @@ -1574,13 +1584,13 @@ /* Set the permissions as they were. */ - fprintf (output, " chmod %04o '%s'\n", - (unsigned) (struct_stat.st_mode & 0777), restore_name); + fprintf (output, " chmod %04o %s\n", + (unsigned) (struct_stat.st_mode & 0777), quoted_restore_name); /* Report an error if any of the above failed. */ - echo_status ("test $? -ne 0", N_("restore of %s failed"), NULL, - restore_name, 0); + echo_status ("test $? -ne 0", N_("restore of '%s' failed"), NULL, + quoted_restore_name, 0); if (md5_count_mode && (fp = fopen (local_name, "r")) != NULL && md5_stream (fp, md5buffer) == 0) @@ -1589,7 +1599,7 @@ size_t cnt; did_md5 = 1; - fprintf (output, md5test_z, restore_name, + fprintf (output, md5test_z, quoted_restore_name, N_("MD5 check failed"), here_delimiter); for (cnt = 0; cnt < 16; ++cnt) @@ -1609,9 +1619,10 @@ /* Validate the transferred file using simple `wc' command. */ FILE *pfp; - char command[BUFSIZ]; + char *command = alloca (strlen (CHARACTER_COUNT_COMMAND) + + strlen (quoted_local_name) + 2); - sprintf (command, "LC_ALL=C wc -c < '%s'", local_name); + sprintf (command, "%s %s", CHARACTER_COUNT_COMMAND, quoted_local_name); if (pfp = popen (command, "r"), pfp) { char wc[BUFSIZ]; @@ -1643,11 +1654,11 @@ } fprintf (output, - "test `LC_ALL=C wc -c < '%s'` -ne %s && \\\n ${echo} ", - restore_name, wc); + "test `LC_ALL=C wc -c < %s` -ne %s && \\\n ${echo} ", + quoted_restore_name, wc); fprintf (output, - N_("'restoration warning: size of %s is not %s'\n"), - restore_name, wc); + N_("'restoration warning: size of '%s' is not %s'\n"), + quoted_restore_name, wc); pclose (pfp); } } --- tests/shar-1.ok +++ tests/shar-1.ok @@ -94,26 +94,26 @@ fi # ============= shar-1.in ============== if test -f 'shar-1.in' && test "$first_param" != -c; then - ${echo} 'x -SKIPPING shar-1.in (file already exists)' + ${echo} 'x -SKIPPING ''shar-1.in'' (file already exists)' else -${echo} 'x - extracting shar-1.in (text)' +${echo} 'x - extracting ''shar-1.in'' (text)' sed 's/^X//' << 'SHAR_EOF' > 'shar-1.in' && This is a test SHAR_EOF (set <date> 'shar-1.in'; eval "$shar_touch") && chmod 0644 'shar-1.in' if test $? -ne 0 -then ${echo} 'restore of shar-1.in failed' +then ${echo} 'restore of ''shar-1.in'' failed' fi if ${md5check} then ( - ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'shar-1.in: MD5 check failed' + ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'shar-1.in': 'MD5 check failed' ) << SHAR_EOF ff22941336956098ae9a564289d1bf1b shar-1.in SHAR_EOF else test `LC_ALL=C wc -c < 'shar-1.in'` -ne 15 && \ - ${echo} 'restoration warning: size of shar-1.in is not 15' + ${echo} 'restoration warning: size of ''shar-1.in'' is not 15' fi fi if rm -fr ${lock_dir}
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor