LCOV - code coverage report
Current view: top level - lib - utimens.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 14 23 60.9 %
Date: 2018-01-30 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* Set file access and modification times.
       2             : 
       3             :    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software
       4             :    Foundation, Inc.
       5             : 
       6             :    This program is free software: you can redistribute it and/or modify it
       7             :    under the terms of the GNU General Public License as published by the
       8             :    Free Software Foundation; either version 3 of the License, or any
       9             :    later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18             : 
      19             : /* Written by Paul Eggert.  */
      20             : 
      21             : /* derived from a function in touch.c */
      22             : 
      23             : #include <config.h>
      24             : 
      25             : #include "utimens.h"
      26             : 
      27             : #include <errno.h>
      28             : #include <fcntl.h>
      29             : #include <sys/time.h>
      30             : #include <unistd.h>
      31             : 
      32             : #if HAVE_UTIME_H
      33             : # include <utime.h>
      34             : #endif
      35             : 
      36             : /* Some systems (even some that do have <utime.h>) don't declare this
      37             :    structure anywhere.  */
      38             : #ifndef HAVE_STRUCT_UTIMBUF
      39             : struct utimbuf
      40             : {
      41             :   long actime;
      42             :   long modtime;
      43             : };
      44             : #endif
      45             : 
      46             : /* Some systems don't have ENOSYS.  */
      47             : #ifndef ENOSYS
      48             : # ifdef ENOTSUP
      49             : #  define ENOSYS ENOTSUP
      50             : # else
      51             : /* Some systems don't have ENOTSUP either.  */
      52             : #  define ENOSYS EINVAL
      53             : # endif
      54             : #endif
      55             : 
      56             : #ifndef __attribute__
      57             : # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
      58             : #  define __attribute__(x)
      59             : # endif
      60             : #endif
      61             : 
      62             : #ifndef ATTRIBUTE_UNUSED
      63             : # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
      64             : #endif
      65             : 
      66             : /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
      67             :    TIMESPEC[0] and TIMESPEC[1], respectively.
      68             :    FD must be either negative -- in which case it is ignored --
      69             :    or a file descriptor that is open on FILE.
      70             :    If FD is nonnegative, then FILE can be NULL, which means
      71             :    use just futimes (or equivalent) instead of utimes (or equivalent),
      72             :    and fail if on an old system without futimes (or equivalent).
      73             :    If TIMESPEC is null, set the time stamps to the current time.
      74             :    Return 0 on success, -1 (setting errno) on failure.  */
      75             : 
      76             : int
      77          58 : gl_futimens (int fd ATTRIBUTE_UNUSED,
      78             :              char const *file, struct timespec const timespec[2])
      79             : {
      80             :   /* Some Linux-based NFS clients are buggy, and mishandle time stamps
      81             :      of files in NFS file systems in some cases.  We have no
      82             :      configure-time test for this, but please see
      83             :      <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
      84             :      some of the problems with Linux 2.6.16.  If this affects you,
      85             :      compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
      86             :      help in some cases, albeit at a cost in performance.  But you
      87             :      really should upgrade your kernel to a fixed version, since the
      88             :      problem affects many applications.  */
      89             : 
      90             : #if HAVE_BUGGY_NFS_TIME_STAMPS
      91             :   if (fd < 0)
      92             :     sync ();
      93             :   else
      94             :     fsync (fd);
      95             : #endif
      96             : 
      97             :   /* There's currently no interface to set file timestamps with
      98             :      nanosecond resolution, so do the best we can, discarding any
      99             :      fractional part of the timestamp.  */
     100             : #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
     101             :   struct timeval timeval[2];
     102             :   struct timeval const *t;
     103          58 :   if (timespec)
     104             :     {
     105          29 :       timeval[0].tv_sec = timespec[0].tv_sec;
     106          29 :       timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
     107          29 :       timeval[1].tv_sec = timespec[1].tv_sec;
     108          29 :       timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
     109          29 :       t = timeval;
     110             :     }
     111             :   else
     112          29 :     t = NULL;
     113             : 
     114             : 
     115          58 :   if (fd < 0)
     116             :     {
     117             : # if HAVE_FUTIMESAT
     118          17 :       return futimesat (AT_FDCWD, file, t);
     119             : # endif
     120             :     }
     121             :   else
     122             :     {
     123             :       /* If futimesat or futimes fails here, don't try to speed things
     124             :          up by returning right away.  glibc can incorrectly fail with
     125             :          errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
     126             :          in high security mode doesn't allow ordinary users to read
     127             :          /proc/self, so glibc incorrectly fails with errno == EACCES.
     128             :          If errno == EIO, EPERM, or EROFS, it's probably safe to fail
     129             :          right away, but these cases are rare enough that they're not
     130             :          worth optimizing, and who knows what other messed-up systems
     131             :          are out there?  So play it safe and fall back on the code
     132             :          below.  */
     133             : # if HAVE_FUTIMESAT
     134          41 :       if (futimesat (fd, NULL, t) == 0)
     135          41 :         return 0;
     136             : # elif HAVE_FUTIMES
     137             :       if (futimes (fd, t) == 0)
     138             :         return 0;
     139             : # endif
     140             :     }
     141             : #endif
     142             : 
     143           0 :   if (!file)
     144             :     {
     145             : #if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
     146             :       errno = ENOSYS;
     147             : #endif
     148             : 
     149             :       /* Prefer EBADF to ENOSYS if both error numbers apply.  */
     150           0 :       if (errno == ENOSYS)
     151             :         {
     152           0 :           int fd2 = dup (fd);
     153           0 :           int dup_errno = errno;
     154           0 :           if (0 <= fd2)
     155           0 :             close (fd2);
     156           0 :           errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
     157             :         }
     158             : 
     159           0 :       return -1;
     160             :     }
     161             : 
     162             : #if HAVE_WORKING_UTIMES
     163           0 :   return utimes (file, t);
     164             : #else
     165             :   {
     166             :     struct utimbuf utimbuf;
     167             :     struct utimbuf const *ut;
     168             :     if (timespec)
     169             :       {
     170             :         utimbuf.actime = timespec[0].tv_sec;
     171             :         utimbuf.modtime = timespec[1].tv_sec;
     172             :         ut = &utimbuf;
     173             :       }
     174             :     else
     175             :       ut = NULL;
     176             : 
     177             :     return utime (file, ut);
     178             :   }
     179             : #endif
     180             : }
     181             : 
     182             : /* Set the access and modification time stamps of FILE to be
     183             :    TIMESPEC[0] and TIMESPEC[1], respectively.  */
     184             : int
     185           3 : utimens (char const *file, struct timespec const timespec[2])
     186             : {
     187           3 :   return gl_futimens (-1, file, timespec);
     188             : }

Generated by: LCOV version 1.10