bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

"touch -" test cases, and fixes for "touch -c - >&-"


From: Paul Eggert
Subject: "touch -" test cases, and fixes for "touch -c - >&-"
Date: Mon, 26 Sep 2005 16:11:00 -0700
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

I some test cases for "touch".  They caused me to discover one minor
bug in the old "touch" code; "close(fd)" could clobber errno (this was
more by code inspection than anything else).  Also, they uncovered
some portability mishaps (causing suboptimal code or incorrect errno
values in diagnostics).  Also, they uncovered the fact that "touch -c
- >&-" should not report an error number, by analogy with "touch -c
no-such-file".

Here's the patch I installed:

2005-09-25  Paul Eggert  <address@hidden>

        * lib/utimens.c: Include unistd.h, for dup2.
        (futimens): Fix typo: HAVE_FUTIMESAT was misspelled in an #if.
        (futimens) [! HAVE_FUTIMESAT]: If !file, set errno before returning -1.
        * src/touch.c (touch): Handle "touch -c - >&-" by checking for EBADF
        and ENOSYS.
        Do not pass "-" to futimens; pass NULL instead.
        If close (STDIN_FILENO) fails, report the error separately instead
        of letting the 'close' pollute errno.
        * tests/touch/empty-file: Test "touch -" too.
        * tests/touch/no-create-missing: Likewise.
        * tests/touch/read-only: Likewise.

Index: lib/utimens.c
===================================================================
RCS file: /fetish/cu/lib/utimens.c,v
retrieving revision 1.9
diff -p -u -r1.9 utimens.c
--- lib/utimens.c       25 Sep 2005 06:08:45 -0000      1.9
+++ lib/utimens.c       26 Sep 2005 22:57:54 -0000
@@ -26,6 +26,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #if HAVE_UTIME_H
 # include <utime.h>
@@ -113,11 +114,24 @@ futimens (int fd ATTRIBUTE_UNUSED,
 # endif
 #endif
 
-#if ! HAVE_FUTIMES_AT
+#if ! HAVE_FUTIMESAT
 
   if (!file)
     {
+# if ! (HAVE_WORKING_UTIMES && HAVE_FUTIMES)
       errno = ENOSYS;
+# endif
+
+      /* Prefer EBADF to ENOSYS if both error numbers apply.  */
+      if (errno == ENOSYS)
+       {
+         int fd2 = dup (fd);
+         int dup_errno = errno;
+         if (0 <= fd2)
+           close (fd2);
+         errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
+       }
+
       return -1;
     }
 
Index: src/touch.c
===================================================================
RCS file: /fetish/cu/src/touch.c,v
retrieving revision 1.135
diff -p -u -r1.135 touch.c
--- src/touch.c 25 Sep 2005 06:12:21 -0000      1.135
+++ src/touch.c 26 Sep 2005 22:57:54 -0000
@@ -154,7 +154,7 @@ touch (const char *file)
            error (0, open_errno, _("creating %s"), quote (file));
          else
            {
-             if (no_create && errno == ENOENT)
+             if (no_create && (errno == ENOENT || errno == EBADF))
                return true;
              error (0, errno, _("failed to get attributes of %s"),
                     quote (file));
@@ -182,9 +182,23 @@ touch (const char *file)
       t = timespec;
     }
 
-  ok = (futimens (fd, file, t) == 0);
+  ok = (futimens (fd, (fd == STDOUT_FILENO ? NULL : file), t) == 0);
+
   if (fd == STDIN_FILENO)
-    ok &= (close (fd) == 0);
+    {
+      if (close (STDIN_FILENO) != 0)
+       {
+         error (0, errno, _("closing %s"), quote (file));
+         return false;
+       }
+    }
+  else if (fd == STDOUT_FILENO)
+    {
+      /* Do not diagnose "touch -c - >&-".  */
+      if (!ok && errno == EBADF && no_create
+         && change_times == (CH_ATIME | CH_MTIME))
+       return true;
+    }
 
   if (!ok)
     {
Index: tests/touch/empty-file
===================================================================
RCS file: /fetish/cu/tests/touch/empty-file,v
retrieving revision 1.7
diff -p -u -r1.7 empty-file
--- tests/touch/empty-file      2 Feb 2000 14:04:47 -0000       1.7
+++ tests/touch/empty-file      26 Sep 2005 22:57:54 -0000
@@ -22,11 +22,13 @@ fail=0
 framework_failure=0
 
 for d in $TOUCH_DIR_LIST; do
-  rm -rf $d/a $d/b
+  rm -rf $d/a $d/b $d/c
   > $d/a || framework_failure=1
   test -f $d/a || framework_failure=1
   > $d/b || framework_failure=1
   test -f $d/b || framework_failure=1
+  > $d/c || framework_failure=1
+  test -f $d/c || framework_failure=1
 done
 
 if test $framework_failure = 1; then
@@ -49,7 +51,12 @@ for d in $TOUCH_DIR_LIST; do
   set x `ls -t $d/a $d/b`
   test "$*" = "x $d/b $d/a" || fail=1
 
-  rm -rf $d/a $d/b
+  if touch - 1< $d/c 2> /dev/null; then
+    set x `ls -t $d/a $d/c`
+    test "$*" = "x $d/c $d/a" || fail=1
+  fi
+
+  rm -rf $d/a $d/b $d/c
 done
 
 if test $fail != 0; then
Index: tests/touch/no-create-missing
===================================================================
RCS file: /fetish/cu/tests/touch/no-create-missing,v
retrieving revision 1.4
diff -p -u -r1.4 no-create-missing
--- tests/touch/no-create-missing       23 Jun 2004 15:07:05 -0000      1.4
+++ tests/touch/no-create-missing       26 Sep 2005 22:57:54 -0000
@@ -25,5 +25,8 @@ fail=0
 touch -c no-file > /dev/null 2>&1 || fail=1
 touch -cm no-file > /dev/null 2>&1 || fail=1
 touch -ca no-file > /dev/null 2>&1 || fail=1
+touch -c - >&- 2> /dev/null || fail=1
+touch -cm - >&- 2> /dev/null || fail=1
+touch -ca - >&- 2> /dev/null || fail=1
 
 (exit $fail); exit $fail
Index: tests/touch/read-only
===================================================================
RCS file: /fetish/cu/tests/touch/read-only,v
retrieving revision 1.1
diff -p -u -r1.1 read-only
--- tests/touch/read-only       26 Sep 2005 07:31:57 -0000      1.1
+++ tests/touch/read-only       26 Sep 2005 22:57:54 -0000
@@ -29,4 +29,6 @@ fail=0
 
 touch read-only || fail=1
 
+touch - 1< read-only 2> /dev/null && { test ! -f - || fail=1; }
+
 (exit $fail); exit $fail





reply via email to

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