]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Merge pull request #2753 from KlaraSystems/des/temp-files
authorTim Kientzle <kientzle@acm.org>
Wed, 29 Oct 2025 00:13:18 +0000 (17:13 -0700)
committerMartin Matuska <martin@matuska.de>
Mon, 17 Nov 2025 19:18:44 +0000 (20:18 +0100)
Create temporary files in the target directory

(cherry picked from commit d2e861769c25470427656b36a14b535f17d47d03)

libarchive/archive_read_disk_entry_from_file.c
libarchive/archive_string.c
libarchive/archive_string.h
libarchive/archive_write_disk_posix.c
libarchive/test/test_archive_string.c

index 42af4034b07ea779969d24c125be41287356f7fe..121af19872e9424f6cb2ec5d1af4c370130f52ff 100644 (file)
@@ -358,12 +358,10 @@ setup_mac_metadata(struct archive_read_disk *a,
                return (ARCHIVE_OK);
 
        archive_string_init(&tempfile);
-       if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) {
-               ret = ARCHIVE_WARN;
-               goto cleanup;
-       }
-       archive_strcat(&tempfile, "tar.md.XXXXXX");
-       tempfd = mkstemp(tempfile.s);
+       archive_strcpy(&tempfile, name);
+       archive_string_dirname(&tempfile);
+       archive_strcat(&tempfile, "/tar.XXXXXXXX");
+       tempfd = __archive_mkstemp(tempfile.s);
        if (tempfd < 0) {
                archive_set_error(&a->archive, errno,
                    "Could not open extended attribute file");
index 3bb978335eb876a635d93cb21a96d285fe9dcffe..740308b6e4e3e6cf3eb859e8015c152507f6d9de 100644 (file)
@@ -2054,6 +2054,26 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
        return (r);
 }
 
+struct archive_string *
+archive_string_dirname(struct archive_string *as)
+{
+       /* strip trailing separators */
+       while (as->length > 1 && as->s[as->length - 1] == '/')
+               as->length--;
+       /* strip final component */
+       while (as->length > 0 && as->s[as->length - 1] != '/')
+               as->length--;
+       /* empty path -> cwd */
+       if (as->length == 0)
+               return (archive_strcat(as, "."));
+       /* strip separator(s) */
+       while (as->length > 1 && as->s[as->length - 1] == '/')
+               as->length--;
+       /* terminate */
+       as->s[as->length] = '\0';
+       return (as);
+}
+
 #if HAVE_ICONV
 
 /*
index e8987867d3ce7e8b828fea925f389ab1eb91a429..d5f5c03aca30c8bf3e38555a6245bdd5f5c13a84 100644 (file)
@@ -192,6 +192,10 @@ void       archive_string_vsprintf(struct archive_string *, const char *,
 void   archive_string_sprintf(struct archive_string *, const char *, ...)
            __LA_PRINTF(2, 3);
 
+/* Equivalent to dirname(3) */
+struct archive_string *
+archive_string_dirname(struct archive_string *);
+
 /* Translates from MBS to Unicode. */
 /* Returns non-zero if conversion failed in any way. */
 int archive_wstring_append_from_mbs(struct archive_wstring *dest,
index 6fcf3929b5cb69091ab8cdf080af8c3afcb14b2c..cd25620305b648b1c8592f58f24fd052c9255e1e 100644 (file)
@@ -412,12 +412,14 @@ static ssize_t    _archive_write_disk_data_block(struct archive *, const void *,
 static int
 la_mktemp(struct archive_write_disk *a)
 {
+       struct archive_string *tmp = &a->_tmpname_data;
        int oerrno, fd;
        mode_t mode;
 
-       archive_string_empty(&a->_tmpname_data);
-       archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
-       a->tmpname = a->_tmpname_data.s;
+       archive_strcpy(tmp, a->name);
+       archive_string_dirname(tmp);
+       archive_strcat(tmp, "/tar.XXXXXXXX");
+       a->tmpname = tmp->s;
 
        fd = __archive_mkstemp(a->tmpname);
        if (fd == -1)
@@ -4287,8 +4289,10 @@ create_tempdatafork(struct archive_write_disk *a, const char *pathname)
        int tmpfd;
 
        archive_string_init(&tmpdatafork);
-       archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
-       tmpfd = mkstemp(tmpdatafork.s);
+       archive_strcpy(&tmpdatafork, pathname);
+       archive_string_dirname(&tmpdatafork);
+       archive_strcat(&tmpdatafork, "/tar.XXXXXXXX");
+       tmpfd = __archive_mkstemp(tmpdatafork.s);
        if (tmpfd < 0) {
                archive_set_error(&a->archive, errno,
                    "Failed to mkstemp");
@@ -4367,8 +4371,10 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
         * silly dance of writing the data to disk just so that
         * copyfile() can read it back in again. */
        archive_string_init(&tmp);
-       archive_strcpy(&tmp, "tar.mmd.XXXXXX");
-       fd = mkstemp(tmp.s);
+       archive_strcpy(&tmp, pathname);
+       archive_string_dirname(&tmp);
+       archive_strcat(&tmp, "/tar.XXXXXXXX");
+       fd = __archive_mkstemp(tmp.s);
 
        if (fd < 0) {
                archive_set_error(&a->archive, errno,
index 30f7a800eae8e4526acf2778ae8af79b576d5f74..bf822c0d5e82fb6c3dea98090adb014cd6e8e027 100644 (file)
@@ -353,6 +353,43 @@ test_archive_string_sprintf(void)
        archive_string_free(&s);
 }
 
+static void
+test_archive_string_dirname(void)
+{
+       static struct pair { const char *str, *exp; } pairs[] = {
+               { "",           "." },
+               { "/",          "/" },
+               { "//",         "/" },
+               { "///",        "/" },
+               { "./",         "." },
+               { ".",          "." },
+               { "..",         "." },
+               { "foo",        "." },
+               { "foo/",       "." },
+               { "foo//",      "." },
+               { "foo/bar",    "foo" },
+               { "foo/bar/",   "foo" },
+               { "foo/bar//",  "foo" },
+               { "foo//bar",   "foo" },
+               { "foo//bar/",  "foo" },
+               { "foo//bar//", "foo" },
+               { "/foo",       "/" },
+               { "//foo",      "/" },
+               { "//foo/",     "/" },
+               { "//foo//",    "/" },
+               { 0 },
+       };
+       struct pair *pair;
+       struct archive_string s;
+
+       archive_string_init(&s);
+       for (pair = pairs; pair->str; pair++) {
+               archive_strcpy(&s, pair->str);
+               archive_string_dirname(&s);
+               assertEqualString(pair->exp, s.s);
+       }
+}
+
 DEFINE_TEST(test_archive_string)
 {
        test_archive_string_ensure();
@@ -364,6 +401,7 @@ DEFINE_TEST(test_archive_string)
        test_archive_string_concat();
        test_archive_string_copy();
        test_archive_string_sprintf();
+       test_archive_string_dirname();
 }
 
 static const char *strings[] =