]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Better xsparse outname guessing
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 2 Aug 2024 18:23:23 +0000 (11:23 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 4 Aug 2024 08:41:43 +0000 (01:41 -0700)
* scripts/xsparse.c (guess_outname): Use simpler algorithm,
that doesn’t mishandle outnames like ‘/foo’.

doc/tar.texi
scripts/xsparse.c

index ddbf8cba01b75c4c5f3e0f9f54d668d98b00f540..2519f97b6d8123d06497c07cb72ef5084ca1a764 100644 (file)
@@ -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,
index 5d7166ae642cc49b43989dd721810e3a67a39b71..704bb266717473451311438e5b2713eb22c966af 100644 (file)
@@ -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