From: Paul Eggert Date: Fri, 2 Aug 2024 18:23:23 +0000 (-0700) Subject: Better xsparse outname guessing X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=44196e198f004df24e9a8e63b33bb20996840280;p=thirdparty%2Ftar.git Better xsparse outname guessing * scripts/xsparse.c (guess_outname): Use simpler algorithm, that doesn’t mishandle outnames like ‘/foo’. --- diff --git a/doc/tar.texi b/doc/tar.texi index ddbf8cba..2519f97b 100644 --- a/doc/tar.texi +++ b/doc/tar.texi @@ -11014,17 +11014,12 @@ will deduce the name for the resulting expanded file using the following algorithm: @enumerate 1 -@item If @file{cond-file} does not contain any directories, -@file{../cond-file} will be used; - -@item If @file{cond-file} has the form -@file{@var{dir}/@var{t}/@var{name}}, where both @var{t} and @var{name} -are simple names, with no @samp{/} characters in them, the output file -name will be @file{@var{dir}/@var{name}}. +@item +If @file{cond-file} has the form @file{@var{dir}/@var{name}}, +the output file name will be @file{@var{dir}/../@var{name}}. -@item Otherwise, if @file{cond-file} has the form -@file{@var{dir}/@var{name}}, the output file name will be -@file{@var{name}}. +@item +Otherwise, the output file name will be @file{../cond-file}. @end enumerate In the unlikely case when this algorithm does not suit your needs, diff --git a/scripts/xsparse.c b/scripts/xsparse.c index 5d7166ae..704bb266 100644 --- a/scripts/xsparse.c +++ b/scripts/xsparse.c @@ -336,43 +336,15 @@ usage (int code) static void guess_outname (char *name) { - char *p; - char *s; - - if (name[0] == '.' && name[1] == '/') - name += 2; - - p = name + strlen (name) - 1; - s = NULL; - - for (; p > name && *p != '/'; p--) - ; - if (*p == '/') - s = p + 1; - if (p != name) - { - for (p--; p > name && *p != '/'; p--) - ; - } - - if (*p != '/') - { - if (s) - outname = s; - else - { - outname = emalloc (4 + strlen (name)); - strcpy (outname, "../"); - strcpy (outname + 3, name); - } - } - else - { - size_t len = p - name + 1; - outname = emalloc (len + strlen (s) + 1); - memcpy (outname, name, len); - strcpy (outname + len, s); - } + char *base = strrchr (name, '/'); + base = base ? base + 1 : name; + size_t dirlen = base - name, baselen = strlen (base); + static char const parentdir[] = "../"; + int parentdirlen = sizeof parentdir - 1; + outname = emalloc (dirlen + parentdirlen + baselen + 1); + memcpy (outname, name, dirlen); + memcpy (outname + dirlen, parentdir, parentdirlen); + memcpy (outname + dirlen + parentdirlen, base, baselen + 1); } int