bug-coreutils
[Top][All Lists]
Advanced

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

[PATCH] cp -p doesn't work with HAVE_FUTIMENS and without /proc


From: Kir Kolyshkin
Subject: [PATCH] cp -p doesn't work with HAVE_FUTIMENS and without /proc
Date: Sat, 15 Apr 2006 02:34:15 +0400
User-agent: Mozilla Thunderbird 1.0.7 (X11/20060217)

I have come across a bug in cp utility from coreutils-5.93 on a Fedora Core 5 system (glibc-2.4), while working on OpenVZ user-level tools.

Original, unpatched versions of coreutils-5.93 and 5.94 are also affected.


PREREQUISITES
-------------
Bug occurs when coreutils is compiled on a system which provides futimens() function, and only if /proc fs is not mounted.


SYMPTOMS
--------
Copying a file with -p (or --preserve=timestamps) option gives the following error message; cp when exits with 1:

cp: preserving times for `dst-file-name': Function not implemented



ANALYSYS
--------
Strace shows that cp tries to call utimes on /proc/self/fd/4, it fails and cp bails out:

open("dst-file-name", O_WRONLY|O_CREAT|O_LARGEFILE, 0100644) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
read(3, "", 4096)                       = 0
utimes("/proc/self/fd/4", {1145050934, 0}) = -1 ENOENT (No such file or directory)
fcntl(4, F_GETFD)                       = 0
write(2, "cp: ", 4cp: )                     = 4
write(2, "preserving times for `dst-file-n"..., 36preserving times for `dst-file-name') = 36
write(2, ": Function not implemented", 26: Function not implemented) = 26
write(2, "\n", 1
)                       = 1


Ltrace shows that cp calls futimens, which fails, and cp bails out:

open64("dst-file-name", 513, 00) = 4 __fxstat64(3, 4, 0xffffc184) = 0 __fxstat64(3, 3, 0xffffc184) = 0 getpagesize() = 4096 read(3, "", 4096) = 0 futimesat(4, 0, -24452, 0x8058a20, 0xf7dbfb94) = -1 __errno_location() = 0xf7d6b690 __errno_location() = 0xf7d6b690 __ctype_get_mb_cur_max(0xf7db25b0, 0xc0b8fae, 0, 0x8048ab0, 494452) = 1 dcgettext(0, 0x8055c2a, 5, 0x80588dc, 0xf7d6b690) = 0x8055c2a dcgettext(0, 0x8055f38, 5, 0x80588dc, 0x8055c2a) = 0x8055f38 strlen("'") = 1 dcgettext(0, 0x80558c1, 5, 0, 0) = 0x80558c1 __errno_location() = 0xf7d6b690 error(0, 38, 0x80558c1, 0x8058b00, 0cp: preserving times for `dst-file-name': Function not implemented
)                                           = 0


CODE
----
The following piece of code from coreutils/lib/utimens.c sheds some light:

# if HAVE_FUTIMESAT
  return fd < 0 ? futimesat (AT_FDCWD, file, t) : futimesat (fd, NULL, t);
# elif HAVE_FUTIMES
  if (0 <= fd)
    {
      if (futimes (fd, t) == 0)
        return 0;

      /* Don't worry about trying to speed things up by returning right
         away here.  glibc futimes can incorrectly fail with errno ==
         ENOENT if /proc isn't mounted.  Also, Mandrake 10.0 in high
         security mode doesn't allow ordinary users to read /proc/self, so
         glibc futimes incorrectly fails with errno == EACCES.  If futimes
         fails with errno == EIO, EPERM, or EROFS, it's probably safe to
         fail right away, but these cases are rare enough that they're not
         worth optimizing, and who knows what other messed-up systems are
         out there?  So play it safe and fall back on the code below.  */
    }
# endif
#endif

Apparently, there is a fallback path for futimes, but there is no such path for futimesat.


FIX
---
Attached is the patch that enables fallback path for futimesat().
--- coreutils-5.93/lib/utimens.c        2005-11-02 15:16:12.000000000 +0300
+++ coreutils-5.93-cp-p-fix/lib/utimens.c       2006-04-14 23:33:49.000000000 
+0400
@@ -92,7 +92,14 @@
     t = NULL;
 
 # if HAVE_FUTIMESAT
-  return fd < 0 ? futimesat (AT_FDCWD, file, t) : futimesat (fd, NULL, t);
+  if (fd < 0)
+    return futimesat (AT_FDCWD, file, t);
+  else if (futimesat (fd, NULL, t) == 0)
+    return 0;
+  /* If futimesat failed, the reason might be that /proc is not mounted
+     or it is otherwise inaccessible. In that case we use the fallback code
+     below. 
+  */
 # elif HAVE_FUTIMES
   if (0 <= fd)
     {
@@ -112,8 +119,6 @@
 # endif
 #endif
 
-#if ! HAVE_FUTIMESAT
-
   if (!file)
     {
 # if ! (HAVE_WORKING_UTIMES && HAVE_FUTIMES)
@@ -151,8 +156,6 @@
     return utime (file, ut);
   }
 # endif
-
-#endif
 }
 
 /* Set the access and modification time stamps of FILE to be

reply via email to

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