From 8378991cba68d4adf74f3cec3d6ab07ed2e325d0 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 27 Feb 2021 16:41:12 -0800 Subject: maint: port to Fedora 33 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fedora 33 uses GCC 10.2.1, which is a bit pickier. * configure.ac: Do not use -Wsystem-headers, as this runs afoul of netdb.h on Fedora 33. * gnulib.modules: Add ‘attribute’. * lib/wordsplit.c (wsnode_new): Return the newly allocated pointer instead of a boolean, to pacify GCC 10.2.1 which otherwise complains about use of possibly-null pointers. All uses changed. * src/buffer.c (try_new_volume): Don’t assume find_next_block succeeds. (_write_volume_label): Pacify GCC 10.2.1 with an ‘assume’, since LABEL must be nonnull here. * src/common.h (FALLTHROUGH): Remove; now in attribute.h. Include attribute.h, for ATTRIBUTE_NONNULL. * src/misc.c (assign_string_or_null): New function, taking over the old role of assign_string. (assign_string): Assume VALUE is non-null. (assign_null): New function, taking over the old role of assign_string when its VALUE was nonnull. All callers of assign_string changed to use these functions. (assign_string_n): Clear *STRING if VALUE is null, to fix a potential double-free. --- configure.ac | 7 +-- gnulib.modules | 1 + lib/wordsplit.c | 141 +++++++++++++++++++++++++++++--------------------------- src/buffer.c | 8 ++-- src/common.h | 12 ++--- src/extract.c | 22 ++++----- src/misc.c | 33 ++++++++++--- 7 files changed, 124 insertions(+), 100 deletions(-) diff --git a/configure.ac b/configure.ac index 8beba5d1..f9d6c8b3 100644 --- a/configure.ac +++ b/configure.ac @@ -112,7 +112,7 @@ if test $ac_cv_lib_error_at_line = no; then AC_DEFINE([ENABLE_ERROR_PRINT_PROGNAME],[1], [Enable the use of error_print_progname to print program name with error messages. See comment to function tar_print_progname in src/tar.c]) -fi +fi # paxutils modules tar_PAXUTILS @@ -162,6 +162,7 @@ if test "$gl_gcc_warnings" = yes; then nw="$nw -Winline" # It's OK to not inline. nw="$nw -Wstrict-overflow" # It's OK to optimize strictly. nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now. + nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings nw="$nw -Wstack-protector" gl_MANYWARN_ALL_GCC([ws]) @@ -173,10 +174,10 @@ if test "$gl_gcc_warnings" = yes; then gl_WARN_ADD([-Wno-type-limits]) # It's OK to optimize based on types. gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now gl_WARN_ADD([-Wno-format-nonliteral]) - + gl_WARN_ADD([-fdiagnostics-show-option]) gl_WARN_ADD([-funit-at-a-time]) - + AC_SUBST([WARN_CFLAGS]) diff --git a/gnulib.modules b/gnulib.modules index 68936094..c2900003 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -23,6 +23,7 @@ areadlinkat-with-size argmatch argp argp-version-etc +attribute backupfile closeout configmake diff --git a/lib/wordsplit.c b/lib/wordsplit.c index 661a4f8b..28390c5b 100644 --- a/lib/wordsplit.c +++ b/lib/wordsplit.c @@ -95,7 +95,7 @@ _wsplt_seterr (struct wordsplit *wsp, int ec) wordsplit_perror (wsp); return ec; } - + static int _wsplt_nomem (struct wordsplit *wsp) { @@ -126,7 +126,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss, unsigned flags, int finalize) { int rc; - + wss->ws_delim = wsp->ws_delim; wss->ws_debug = wsp->ws_debug; wss->ws_error = wsp->ws_error; @@ -150,7 +150,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss, } wss->ws_options = wsp->ws_options; - + flags |= WRDSF_DELIM | WRDSF_ALLOC_DIE | WRDSF_ERROR @@ -209,7 +209,7 @@ wordsplit_init0 (struct wordsplit *wsp) } char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v"; - + static int wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, unsigned flags) @@ -282,7 +282,7 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, { wsp->ws_escape[WRDSX_WORD] = wordsplit_c_escape_tab; wsp->ws_escape[WRDSX_QUOTE] = wordsplit_c_escape_tab; - wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD + wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD; } else @@ -292,16 +292,16 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, wsp->ws_options |= WRDSO_BSKEEP_QUOTE; } } - + wsp->ws_endp = 0; wsp->ws_wordi = 0; if (wsp->ws_flags & WRDSF_REUSE) wordsplit_free_nodes (wsp); wsp->ws_head = wsp->ws_tail = NULL; - + wordsplit_init0 (wsp); - + return 0; } @@ -424,14 +424,13 @@ wsnode_len (struct wordsplit_node *p) return p->v.segm.end - p->v.segm.beg; } -static int -wsnode_new (struct wordsplit *wsp, struct wordsplit_node **pnode) +static struct wordsplit_node * +wsnode_new (struct wordsplit *wsp) { struct wordsplit_node *node = calloc (1, sizeof (*node)); if (!node) - return _wsplt_nomem (wsp); - *pnode = node; - return 0; + _wsplt_nomem (wsp); + return node; } static void @@ -527,14 +526,11 @@ wsnode_insert (struct wordsplit *wsp, struct wordsplit_node *node, static int wordsplit_add_segm (struct wordsplit *wsp, size_t beg, size_t end, int flg) { - struct wordsplit_node *node; - int rc; - if (end == beg && !(flg & _WSNF_EMPTYOK)) return 0; - rc = wsnode_new (wsp, &node); - if (rc) - return rc; + struct wordsplit_node *node = wsnode_new (wsp); + if (!node) + return 1; node->flags = flg & ~(_WSNF_WORD | _WSNF_EMPTYOK); node->v.segm.beg = beg; node->v.segm.end = end; @@ -587,7 +583,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node) if (!(node->flags & _WSNF_JOIN)) return 0; - + for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next) { len += wsnode_len (p); @@ -717,7 +713,7 @@ wordsplit_finish (struct wordsplit *wsp) Nodes of type _WSNF_DELIM get inserted to the node list if either WRDSF_RETURN_DELIMS flag or WRDSO_MAXWORDS option is set. - + The following cases should be distinguished: 1. If both WRDSF_SQUEEZE_DELIMS and WRDSF_RETURN_DELIMS are set, compress @@ -781,7 +777,7 @@ wordsplit_finish (struct wordsplit *wsp) continue; } } - else + else { if (delim) { @@ -900,11 +896,11 @@ node_split_prefix (struct wordsplit *wsp, struct wordsplit_node *node, size_t beg, size_t len, int flg) { - struct wordsplit_node *newnode; if (len == 0) return 0; - if (wsnode_new (wsp, &newnode)) + struct wordsplit_node *newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); if (node->flags & _WSNF_WORD) @@ -958,7 +954,7 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff, break; } break; - + case '"': state = st_dquote; break; @@ -1038,7 +1034,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, { int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1; char *v; - + if (wsp->ws_envidx + n >= wsp->ws_envsiz) { size_t sz; @@ -1055,7 +1051,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, for (; wsp->ws_env[i]; i++) ; } - + sz = i + n + 1; newenv = calloc (sz, sizeof(newenv[0])); @@ -1075,7 +1071,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, } } newenv[j] = NULL; - + wsp->ws_envbuf = newenv; wsp->ws_envidx = i; wsp->ws_envsiz = sz; @@ -1104,7 +1100,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, wsp->ws_env = (const char**) wsp->ws_envbuf; } } - + if (wsp->ws_flags & WRDSF_ENV_KV) { /* A key-value pair environment */ @@ -1149,7 +1145,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, const char *start = str - 1; int rc; struct wordsplit ws; - + if (ISVARBEG (str[0])) { for (i = 1; i < len; i++) @@ -1166,7 +1162,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, if (str[i] == ':') { size_t j; - + defstr = str + i + 1; if (find_closing_paren (str, i + 1, len, &j, "{}")) return _wsplt_seterr (wsp, WRDSE_CBRACE); @@ -1182,7 +1178,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, else if (strchr ("-+?=", str[i])) { size_t j; - + defstr = str + i; if (find_closing_paren (str, i, len, &j, "{}")) return _wsplt_seterr (wsp, WRDSE_CBRACE); @@ -1195,7 +1191,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else { - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1247,7 +1244,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, rc = WRDSE_UNDEF; } } - + switch (rc) { case WRDSE_OK: @@ -1267,7 +1264,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, wordsplit_free (&ws); } break; - + case WRDSE_UNDEF: if (defstr) { @@ -1287,11 +1284,11 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, value = ws.ws_wordv[0]; ws.ws_wordv[0] = NULL; wordsplit_free (&ws); - + if (defstr[-1] == '=') wsplt_assign_var (wsp, str, i, value); } - else + else { if (*defstr == '?') { @@ -1339,7 +1336,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } } break; - + case WRDSE_NOSPACE: return _wsplt_nomem (wsp); @@ -1357,7 +1354,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, { if (flg & _WSNF_QUOTE) { - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) { free (value); return 1; @@ -1371,7 +1369,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, { free (value); /* Empty string is a special case */ - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1381,7 +1380,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, { struct wordsplit ws; int rc; - + rc = _wsplt_subsplit (wsp, &ws, value, strlen (value), WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE @@ -1404,7 +1403,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, { size_t size = *pend - start + 1; - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1417,7 +1417,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else { - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1486,7 +1487,7 @@ node_expand (struct wordsplit *wsp, struct wordsplit_node *node, } return 0; } - + /* Remove NULL nodes from the list */ static void wsnode_nullelim (struct wordsplit *wsp) @@ -1539,7 +1540,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, size_t j; char *value; struct wordsplit_node *newnode; - + str++; len--; @@ -1566,7 +1567,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, } else rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure); - + if (rc == WRDSE_NOSPACE) return _wsplt_nomem (wsp); else if (rc) @@ -1585,7 +1586,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, { if (flg & _WSNF_QUOTE) { - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1596,7 +1598,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, { free (value); /* Empty string is a special case */ - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1627,7 +1630,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, } else { - if (wsnode_new (wsp, &newnode)) + newnode = wsnode_new (wsp); + if (!newnode) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; @@ -1674,13 +1678,13 @@ wordsplit_trimws (struct wordsplit *wsp) ; p->v.segm.beg = n; } - + while (p->next && (p->flags & _WSNF_JOIN)) p = p->next; - + if (p->flags & _WSNF_QUOTE) continue; - + /* Trim trailing whitespace */ for (n = p->v.segm.end; n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--); @@ -1699,7 +1703,7 @@ wordsplit_tildexpand (struct wordsplit *wsp) struct wordsplit_node *p; char *uname = NULL; size_t usize = 0; - + for (p = wsp->ws_head; p; p = p->next) { const char *str; @@ -1714,7 +1718,7 @@ wordsplit_tildexpand (struct wordsplit *wsp) size_t slen = wsnode_len (p); struct passwd *pw; char *newstr; - + for (i = 1; i < slen && str[i] != '/'; i++) ; if (i == slen) @@ -1788,7 +1792,7 @@ wordsplit_pathexpand (struct wordsplit *wsp) if (wsp->ws_options & WRDSO_DOTGLOB) flags = GLOB_PERIOD; #endif - + for (p = wsp->ws_head; p; p = next) { const char *str; @@ -1807,23 +1811,23 @@ wordsplit_pathexpand (struct wordsplit *wsp) glob_t g; struct wordsplit_node *prev; char *pattern; - + pattern = malloc (slen + 1); if (!pattern) return _wsplt_nomem (wsp); memcpy (pattern, str, slen); pattern[slen] = 0; - + switch (glob (pattern, flags, NULL, &g)) { case 0: free (pattern); break; - + case GLOB_NOSPACE: free (pattern); return _wsplt_nomem (wsp); - + case GLOB_NOMATCH: if (wsp->ws_options & WRDSO_NULLGLOB) { @@ -1846,7 +1850,7 @@ wordsplit_pathexpand (struct wordsplit *wsp) } free (pattern); continue; - + default: free (pattern); return _wsplt_seterr (wsp, WRDSE_GLOBERR); @@ -1855,10 +1859,10 @@ wordsplit_pathexpand (struct wordsplit *wsp) prev = p; for (i = 0; i < g.gl_pathc; i++) { - struct wordsplit_node *newnode; + struct wordsplit_node *newnode = wsnode_new (wsp); char *newstr; - - if (wsnode_new (wsp, &newnode)) + + if (!newnode) return 1; newstr = strdup (g.gl_pathv[i]); if (!newstr) @@ -1975,7 +1979,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all) int join = 0; unsigned flags = 0; struct wordsplit_node *np = wsp->ws_tail; - + size_t i = start; if (i >= len) @@ -2064,7 +2068,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all) wsp->ws_endp = i; if (wsp->ws_flags & WRDSF_INCREMENTAL) return _WRDS_EOF; - + if (consume_all) { if (!np) @@ -2075,7 +2079,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all) np = np->next; } } - + return _WRDS_OK; } @@ -2342,7 +2346,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) if (wsp->ws_flags & WRDSF_SHOWDBG) wsp->ws_debug (_("(%02d) Input:%.*s;"), wsp->ws_lvl, (int) wsp->ws_len, wsp->ws_input); - + if ((wsp->ws_flags & WRDSF_NOSPLIT) || ((wsp->ws_options & WRDSO_MAXWORDS) && wsp->ws_wordi + 1 == wsp->ws_maxwords)) @@ -2438,7 +2442,7 @@ wordsplit_run (const char *command, size_t length, struct wordsplit *wsp, } int -wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, +wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, unsigned flags) { return wordsplit_run (command, length, wsp, flags, 0); @@ -2559,4 +2563,3 @@ wordsplit_perror (struct wordsplit *wsp) wsp->ws_error ("%s", wordsplit_strerror (wsp)); } } - diff --git a/src/buffer.c b/src/buffer.c index 958085f6..e4386252 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "common.h" #include @@ -1325,8 +1326,8 @@ new_volume (enum access_mode mode) if (verify_option) verify_volume (); - assign_string (&volume_label, NULL); - assign_string (&continued_file_name, NULL); + assign_null (&volume_label); + assign_null (&continued_file_name); continued_file_size = continued_file_offset = 0; current_block = record_start; @@ -1505,7 +1506,7 @@ try_new_volume (void) ASSIGN_STRING_N (&volume_label, current_header->header.name); set_next_block_after (header); header = find_next_block (); - if (header->header.typeflag != GNUTYPE_MULTIVOL) + if (! (header && header->header.typeflag == GNUTYPE_MULTIVOL)) break; FALLTHROUGH; case GNUTYPE_MULTIVOL: @@ -1688,6 +1689,7 @@ _write_volume_label (const char *str) { union block *label = find_next_block (); + assume (label); memset (label, 0, BLOCKSIZE); strcpy (label->header.name, str); diff --git a/src/common.h b/src/common.h index 5d079569..3af33298 100644 --- a/src/common.h +++ b/src/common.h @@ -43,18 +43,13 @@ # define GLOBAL extern #endif -#if 7 <= __GNUC__ -# define FALLTHROUGH __attribute__ ((__fallthrough__)) -#else -# define FALLTHROUGH ((void) 0) -#endif - #define TAREXIT_SUCCESS PAXEXIT_SUCCESS #define TAREXIT_DIFFERS PAXEXIT_DIFFERS #define TAREXIT_FAILURE PAXEXIT_FAILURE #include "arith.h" +#include #include #include #include @@ -633,7 +628,10 @@ void skip_member (void); #define max(a, b) ((a) < (b) ? (b) : (a)) char const *quote_n_colon (int n, char const *arg); -void assign_string (char **dest, const char *src); +void assign_string_or_null (char **dest, const char *src) + ATTRIBUTE_NONNULL ((1)); +void assign_string (char **dest, const char *src) ATTRIBUTE_NONNULL ((1, 2)); +void assign_null (char **dest) ATTRIBUTE_NONNULL ((1)); void assign_string_n (char **string, const char *value, size_t n); #define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v)) int unquote_string (char *str); diff --git a/src/extract.c b/src/extract.c index 80009a54..85a6f1b2 100644 --- a/src/extract.c +++ b/src/extract.c @@ -520,7 +520,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st, data->change_dir = chdir_current; data->cntx_name = NULL; if (st) - assign_string (&data->cntx_name, st->cntx_name); + assign_string_or_null (&data->cntx_name, st->cntx_name); if (st && st->acls_a_ptr) { data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1); @@ -1329,7 +1329,7 @@ extract_file (char *file_name, int typeflag) first. If it doesn't exist, there is no matching entry in the list. Otherwise, look for the entry in list which has the matching dev and ino numbers. - + This approach avoids scanning the singly-linked list in obvious cases and does not rely on comparing file names, which may differ for various reasons (e.g. relative vs. absolute file names). @@ -1342,14 +1342,14 @@ find_delayed_link_source (char const *name) if (!delayed_link_head) return NULL; - + if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW)) { if (errno != ENOENT) stat_error (name); return NULL; } - + for (dl = delayed_link_head; dl; dl = dl->next) { if (dl->dev == st.st_dev && dl->ino == st.st_ino) @@ -1357,7 +1357,7 @@ find_delayed_link_source (char const *name) } return dl; } - + /* Create a placeholder file with name FILE_NAME, which will be replaced after other extraction is done by a symbolic link if IS_SYMLINK is true, and by a hard link otherwise. Set @@ -1385,7 +1385,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made, */ return 0; } - + switch (maybe_recoverable (file_name, false, interdir_made)) { case RECOVER_OK: @@ -1442,7 +1442,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made, p->sources->next = 0; strcpy (p->sources->string, file_name); p->cntx_name = NULL; - assign_string (&p->cntx_name, current_stat_info.cntx_name); + assign_string_or_null (&p->cntx_name, current_stat_info.cntx_name); p->acls_a_ptr = NULL; p->acls_a_len = 0; p->acls_d_ptr = NULL; @@ -1467,7 +1467,7 @@ extract_link (char *file_name, int typeflag) char const *link_name; int rc; struct delayed_link *dl; - + link_name = current_stat_info.link_name; if (! absolute_names_option && contains_dot_dot (link_name)) @@ -1475,7 +1475,7 @@ extract_link (char *file_name, int typeflag) dl = find_delayed_link_source (link_name); if (dl) return create_placeholder_file (file_name, false, &interdir_made, dl); - + do { struct stat st1, st2; @@ -1697,7 +1697,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun) case GNUTYPE_VOLHDR: return false; - + case GNUTYPE_MULTIVOL: ERROR ((0, 0, _("%s: Cannot extract -- file is continued from another volume"), @@ -1753,7 +1753,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun) } } *fun = extractor; - + return true; } diff --git a/src/misc.c b/src/misc.c index 6819c467..3e6ce78f 100644 --- a/src/misc.c +++ b/src/misc.c @@ -42,11 +42,28 @@ quote_n_colon (int n, char const *arg) /* Assign STRING to a copy of VALUE if not zero, or to zero. If STRING was nonzero, it is freed first. */ +void +assign_string_or_null (char **string, const char *value) +{ + if (value) + assign_string (string, value); + else + assign_null (string); +} + void assign_string (char **string, const char *value) { free (*string); - *string = value ? xstrdup (value) : 0; + *string = xstrdup (value); +} + +void +assign_null (char **string) +{ + char *old = *string; + *string = NULL; + free (old); } void @@ -61,6 +78,8 @@ assign_string_n (char **string, const char *value, size_t n) p[l] = 0; *string = p; } + else + *string = NULL; } #if 0 @@ -715,7 +734,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive) possible, real problems are unlikely. Doing any better would require a convention, GNU-wide, for all programs doing backups. */ - assign_string (&after_backup_name, 0); + assign_null (&after_backup_name); /* Check if we really need to backup the file. */ @@ -758,7 +777,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive) ERROR ((0, e, _("%s: Cannot rename to %s"), quotearg_colon (before_backup_name), quote_n (1, after_backup_name))); - assign_string (&after_backup_name, 0); + assign_null (&after_backup_name); return false; } } @@ -782,7 +801,7 @@ undo_last_backup (void) fprintf (stdlis, _("Renaming %s back to %s\n"), quote_n (0, after_backup_name), quote_n (1, before_backup_name)); - assign_string (&after_backup_name, 0); + assign_null (&after_backup_name); } } @@ -1041,11 +1060,11 @@ tar_getcdpath (int idx) { int i; int save_cwdi = chdir_current; - + for (i = idx; i >= 0; i--) if (wd[i].abspath) break; - + while (++i <= idx) { chdir_do (i); @@ -1069,7 +1088,7 @@ tar_getcdpath (int idx) chdir_do (save_cwdi); } - + return wd[idx].abspath; } -- cgit v1.2.1