From d479b2cc9160d9c2fb61afbc9ee70c2faadf80db Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 12 Apr 2026 23:58:22 -0700 Subject: [PATCH] Use mkdtempat instead of mkdtemp This fixes an interaction of -C with incremental 'X'. Problem reported by Pavel Cahyna. * gnulib.modules: Remove mkdtemp. Add tempname, since our mkdtempat uses it. * lib/mkdtempat.c, lib/mkdtempat.h: New files. * lib/Makefile.am (noinst_HEADERS): Add mkdtempat.h. (libtar_a_SOURCES): Add mkdtempat.c. * src/incremen.c: Include mkdtempat.h. (purge_directory): Use mkdtempat, not mkdtemp. --- gnulib.modules | 2 +- lib/Makefile.am | 2 ++ lib/mkdtempat.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ lib/mkdtempat.h | 1 + src/incremen.c | 5 ++++- 5 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 lib/mkdtempat.c create mode 100644 lib/mkdtempat.h diff --git a/gnulib.modules b/gnulib.modules index 17ef44fd..0dc024fe 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -80,7 +80,6 @@ mbrtoc32-regular mcel-prefer mempcpy mkdirat -mkdtemp mkfifoat modechange nstrftime-limited @@ -115,6 +114,7 @@ stringeq strnlen symlinkat sys_stat-h +tempname time_rz timespec timespec-sub diff --git a/lib/Makefile.am b/lib/Makefile.am index 2baa7be5..4888ed36 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -30,6 +30,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu AM_CFLAGS = $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS) noinst_HEADERS = \ + mkdtempat.h\ paxlib.h\ rmt.h\ system.h\ @@ -37,6 +38,7 @@ noinst_HEADERS = \ xattr-at.h libtar_a_SOURCES = \ + mkdtempat.c\ paxerror.c paxexit-status.c paxlib.h paxnames.c \ rtapelib.c \ rmt.h \ diff --git a/lib/mkdtempat.c b/lib/mkdtempat.c new file mode 100644 index 00000000..e35b9bba --- /dev/null +++ b/lib/mkdtempat.c @@ -0,0 +1,45 @@ +/* Copyright 2026 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 3 of the License, 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, see . + + Written by Paul Eggert. */ + +#include + +#include "mkdtempat.h" + +#include + +#include +#include + +static int +try_dir (char *tmpl, void *flags) +{ + int *pdirfd = flags; + return mkdirat (*pdirfd, tmpl, S_IRUSR | S_IWUSR | S_IXUSR); +} + +/* Relative to the directory DIRFD if XTEMPLATE is relative, + generate a unique temporary directory from XTEMPLATE. + The last six characters of XTEMPLATE must be "XXXXXX"; + replace them with a string that makes the generated directory unique. + Create the directory mode 700, and return its name. + On failure, return NULL and set errno. */ +char * +mkdtempat (int dirfd, char *xtemplate) +{ + return (try_tempname_len (xtemplate, 0, &dirfd, try_dir, 6) < 0 + ? NULL : xtemplate); +} diff --git a/lib/mkdtempat.h b/lib/mkdtempat.h new file mode 100644 index 00000000..03a18dc1 --- /dev/null +++ b/lib/mkdtempat.h @@ -0,0 +1 @@ +char *mkdtempat (int, char *); diff --git a/src/incremen.c b/src/incremen.c index 923c6323..53c6b3f3 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include "common.h" @@ -1665,7 +1666,9 @@ purge_directory (char const *directory_name) *copy_end = '/'; memcpy (copy_end + !ISSLASH (copy_end[-1]), TEMP_DIR_TEMPLATE, sizeof TEMP_DIR_TEMPLATE); - if (!mkdtemp (temp_stub)) + struct fdbase f = fdbase (temp_stub); + if (f.fd == BADFD + || !mkdtempat (f.fd, temp_stub + (f.base - temp_stub))) { paxerror (errno, _("Cannot create temporary directory using template %s"), quote (temp_stub)); -- 2.47.3