[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: bug or feature with `mkdir -pv`
From: |
Paul Eggert |
Subject: |
Re: bug or feature with `mkdir -pv` |
Date: |
Sat, 07 Oct 2006 00:13:53 -0700 |
User-agent: |
Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux) |
address@hidden writes:
> $ rm -rf /tmp/foo
> $ touch bar
> $ install -Dv bar /tmp/foo/a/b/c/d
> install: creating directory `__libc_start_main'
Thanks for reporting that. I see now that my patch was too tricky
for its own good. I installed this simpler patch instead.
(CC'ing to gnulib since some of it affects gnulib.)
2006-10-06 Paul Eggert <address@hidden>
Fix bug reported today by Mike Frysinger: mkdir -pv is logging the
wrong file name in some cases. Lars Wendler reported a bug in
my original fix.
* lib/mkancesdirs.c (mkancesdirs): Pass to MAKE_DIR both the full file
name (relative to the original working directory) and the file
name component (relative to the temporary working directory). All
callers changed.
* lib/mkancesdirs.h (mkancesdirs): Adjust prototype to match.
* lib/mkdir-p.c (make_dir_parents): Likewise.
* lib/mkdir-p.h (make_dir_parents): Likewise.
* src/install.c (make_ancestor): New arg COMPONENT.
* src/mkdir.c (make_ancestor): Likewise.
* tests/install/basic-1: Check for install -Dv bug.
* tests/mkdir/Makefile.am (TESTS): Add p-v.
* tests/mkdir/p-v: New file, to test this bug.
Index: lib/mkancesdirs.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/mkancesdirs.c,v
retrieving revision 1.3
diff -p -u -r1.3 mkancesdirs.c
--- lib/mkancesdirs.c 16 Sep 2006 19:58:25 -0000 1.3
+++ lib/mkancesdirs.c 7 Oct 2006 07:06:17 -0000
@@ -42,12 +42,12 @@
savewd.
Create any ancestor directories that don't already exist, by
- invoking MAKE_DIR (COMPONENT, MAKE_DIR_ARG). This function should
- return 0 if successful and the resulting directory is readable, 1
- if successful but the resulting directory might not be readable, -1
- (setting errno) otherwise. If COMPONENT is relative, it is
- relative to the temporary working directory, which may differ from
- *WD.
+ invoking MAKE_DIR (FILE, COMPONENT, MAKE_DIR_ARG). This function
+ should return 0 if successful and the resulting directory is
+ readable, 1 if successful but the resulting directory might not be
+ readable, -1 (setting errno) otherwise. If COMPONENT is relative,
+ it is relative to the temporary working directory, which may differ
+ from *WD.
Ordinarily MAKE_DIR is executed with the working directory changed
to reflect the already-made prefix, and mkancesdirs returns with
@@ -66,7 +66,7 @@
ptrdiff_t
mkancesdirs (char *file, struct savewd *wd,
- int (*make_dir) (char const *, void *),
+ int (*make_dir) (char const *, char const *, void *),
void *make_dir_arg)
{
/* Address of the previous directory separator that follows an
@@ -114,7 +114,7 @@ mkancesdirs (char *file, struct savewd *
&& component[0] == '.' && component[1] == '.')
made_dir = false;
else
- switch (make_dir (component, make_dir_arg))
+ switch (make_dir (file, component, make_dir_arg))
{
case -1:
make_dir_errno = errno;
Index: lib/mkancesdirs.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/mkancesdirs.h,v
retrieving revision 1.2
diff -p -u -r1.2 mkancesdirs.h
--- lib/mkancesdirs.h 16 Sep 2006 19:58:25 -0000 1.2
+++ lib/mkancesdirs.h 7 Oct 2006 07:06:17 -0000
@@ -1,4 +1,4 @@
#include <stddef.h>
struct savewd;
ptrdiff_t mkancesdirs (char *, struct savewd *,
- int (*) (char const *, void *), void *);
+ int (*) (char const *, char const *, void *), void *);
Index: lib/mkdir-p.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/mkdir-p.c,v
retrieving revision 1.9
diff -p -u -r1.9 mkdir-p.c
--- lib/mkdir-p.c 28 Sep 2006 12:18:58 -0000 1.9
+++ lib/mkdir-p.c 7 Oct 2006 07:06:17 -0000
@@ -43,7 +43,7 @@
WD is the working directory, as in savewd.c.
If MAKE_ANCESTOR is not null, create any ancestor directories that
- don't already exist, by invoking MAKE_ANCESTOR (ANCESTOR, OPTIONS).
+ don't already exist, by invoking MAKE_ANCESTOR (DIR, ANCESTOR, OPTIONS).
This function should return zero if successful, -1 (setting errno)
otherwise. In this case, DIR may be modified by storing '\0' bytes
into it, to access the ancestor directories, and this modification
@@ -83,7 +83,7 @@
bool
make_dir_parents (char *dir,
struct savewd *wd,
- int (*make_ancestor) (char const *, void *),
+ int (*make_ancestor) (char const *, char const *, void *),
void *options,
mode_t mode,
void (*announce) (char const *, void *),
Index: lib/mkdir-p.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/mkdir-p.h,v
retrieving revision 1.4
diff -p -u -r1.4 mkdir-p.h
--- lib/mkdir-p.h 16 Sep 2006 19:58:25 -0000 1.4
+++ lib/mkdir-p.h 7 Oct 2006 07:06:17 -0000
@@ -25,7 +25,8 @@
struct savewd;
bool make_dir_parents (char *dir,
struct savewd *wd,
- int (*make_ancestor) (char const *, void *),
+ int (*make_ancestor) (char const *, char const *,
+ void *),
void *options,
mode_t mode,
void (*announce) (char const *, void *),
Index: src/install.c
===================================================================
RCS file: /fetish/cu/src/install.c,v
retrieving revision 1.195
diff -p -u -r1.195 install.c
--- src/install.c 16 Sep 2006 20:03:56 -0000 1.195
+++ src/install.c 7 Oct 2006 07:05:38 -0000
@@ -79,7 +79,8 @@ static bool install_file_in_file (const
static void get_ids (void);
static void strip (char const *name);
static void announce_mkdir (char const *dir, void *options);
-static int make_ancestor (char const *dir, void *options);
+static int make_ancestor (char const *dir, char const *component,
+ void *options);
void usage (int status);
/* The name this program was run with, for error messages. */
@@ -629,11 +630,13 @@ announce_mkdir (char const *dir, void *o
error (0, 0, _("creating directory %s"), quote (dir));
}
-/* Make ancestor directory DIR, with options OPTIONS. */
+/* Make ancestor directory DIR, whose last file name component is
+ COMPONENT, with options OPTIONS. Assume the working directory is
+ COMPONENT's parent. */
static int
-make_ancestor (char const *dir, void *options)
+make_ancestor (char const *dir, char const *component, void *options)
{
- int r = mkdir (dir, DEFAULT_MODE);
+ int r = mkdir (component, DEFAULT_MODE);
if (r == 0)
announce_mkdir (dir, options);
return r;
Index: src/mkdir.c
===================================================================
RCS file: /fetish/cu/src/mkdir.c,v
retrieving revision 1.106
diff -p -u -r1.106 mkdir.c
--- src/mkdir.c 16 Sep 2006 20:03:56 -0000 1.106
+++ src/mkdir.c 7 Oct 2006 07:05:39 -0000
@@ -81,7 +81,7 @@ struct mkdir_options
{
/* Function to make an ancestor, or NULL if ancestors should not be
made. */
- int (*make_ancestor_function) (char const *, void *);
+ int (*make_ancestor_function) (char const *, char const *, void *);
/* Mode for ancestor directory. */
mode_t ancestor_mode;
@@ -105,15 +105,16 @@ announce_mkdir (char const *dir, void *o
error (0, 0, o->created_directory_format, quote (dir));
}
-/* Make ancestor directory DIR, with options OPTIONS. Return 0 if
- successful and the resulting directory is readable, 1 if successful
- but the resulting directory is not readable, -1 (setting errno)
- otherwise. */
+/* Make ancestor directory DIR, whose last component is COMPONENT,
+ with options OPTIONS. Assume the working directory is COMPONENT's
+ parent. Return 0 if successful and the resulting directory is
+ readable, 1 if successful but the resulting directory is not
+ readable, -1 (setting errno) otherwise. */
static int
-make_ancestor (char const *dir, void *options)
+make_ancestor (char const *dir, char const *component, void *options)
{
struct mkdir_options const *o = options;
- int r = mkdir (dir, o->ancestor_mode);
+ int r = mkdir (component, o->ancestor_mode);
if (r == 0)
{
r = ! (o->ancestor_mode & S_IRUSR);
Index: tests/install/basic-1
===================================================================
RCS file: /fetish/cu/tests/install/basic-1,v
retrieving revision 1.22
diff -p -u -r1.22 basic-1
--- tests/install/basic-1 5 Oct 2006 08:43:25 -0000 1.22
+++ tests/install/basic-1 7 Oct 2006 07:05:39 -0000
@@ -24,6 +24,14 @@ if test "$VERBOSE" = yes; then
ginstall --version
fi
+# Make sure we get English translations.
+LANGUAGE=C
+export LANGUAGE
+LC_ALL=C
+export LC_ALL
+LANG=C
+export LANG
+
. $srcdir/../envvar-check
PRIV_CHECK_ARG=require-non-root . $srcdir/../priv-check
@@ -130,4 +138,14 @@ test -d xx/zz || fail=1
test -d sub1/d/rel/a || fail=1
test -d sub1/d/rel/b || fail=1
+touch file || fail=1
+ginstall -Dv file sub3/a/b/c/file >out 2>&1 || fail=1
+diff - out <<\EOF || fail=1
+ginstall: creating directory `sub3'
+ginstall: creating directory `sub3/a'
+ginstall: creating directory `sub3/a/b'
+ginstall: creating directory `sub3/a/b/c'
+`file' -> `sub3/a/b/c/file'
+EOF
+
(exit $fail); exit $fail
Index: tests/mkdir/Makefile.am
===================================================================
RCS file: /fetish/cu/tests/mkdir/Makefile.am,v
retrieving revision 1.16
retrieving revision 1.17
diff -p -u -r1.16 -r1.17
--- tests/mkdir/Makefile.am 3 Jul 2006 12:55:33 -0000 1.16
+++ tests/mkdir/Makefile.am 6 Oct 2006 20:44:32 -0000 1.17
@@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = 1.1 gnits
TESTS = \
p-thru-slink \
- p-3 p-1 p-2 special-1 perm parents t-slash p-slashdot
+ p-3 p-1 p-2 p-v special-1 perm parents t-slash p-slashdot
EXTRA_DIST = $(TESTS)
TESTS_ENVIRONMENT = \
srcdir=$(srcdir) \
--- /dev/null 2005-09-24 22:00:15.000000000 -0700
+++ tests/mkdir/p-v 2006-10-06 13:42:26.000000000 -0700
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Test mkdir -pv.
+
+# Copyright (C) 2006 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 2 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+if test "$VERBOSE" = yes; then
+ set -x
+ mkdir --version
+fi
+
+# Make sure we get English translations.
+LANGUAGE=C
+export LANGUAGE
+LC_ALL=C
+export LC_ALL
+LANG=C
+export LANG
+
+pwd=`pwd`
+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
+trap 'status=$?; cd $pwd; rm -rf $t0 && exit $status' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+framework_failure=0
+mkdir -p $tmp || framework_failure=1
+cd $tmp || framework_failure=1
+
+if test $framework_failure = 1; then
+ echo "$0: failure in testing framework" 1>&2
+ (exit 1); exit 1
+fi
+
+mkdir -pv foo/a/b/c/d 2>out || exit
+
+diff - out <<\EOF
+mkdir: created directory `foo'
+mkdir: created directory `foo/a'
+mkdir: created directory `foo/a/b'
+mkdir: created directory `foo/a/b/c'
+mkdir: created directory `foo/a/b/c/d'
+EOF