bug-coreutils
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]