bug-coreutils
[Top][All Lists]
Advanced

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

Minor performance improvements and cleanups for "touch".


From: Paul Eggert
Subject: Minor performance improvements and cleanups for "touch".
Date: Tue, 23 Nov 2004 12:46:52 -0800
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I installed this:

2004-11-23  Paul Eggert  <address@hidden>

        Minor performance improvements and cleanups for "touch".
        * src/touch.c (posix_date): Remove; not needed as a static var.
        All uses rewritten.
        (touch): Use new futimens function to operate more efficiently
        in some cases.  Don't stat/fstat existing file when
        (!amtime_now && change_times == (CH_ATIME | CH_MTIME)); the
        old time stamps aren't needed in that case.
        (main): change_times is int, not bool.  Simplify test for
        change_times.

        * lib/utimens.c (__attribute__, ATTRIBUTE_UNUSED): New macros.
        (futimens): New function, which uses futimes if available.
        (futimens, utimens): Support timespec==NULL, with same semantics
        as utime and utimens.
        * lib/utimens.h (futimens): New decl.

        * m4/utimens.m4 (gl_UTIMENS): Check for futimes function.

Index: src/touch.c
===================================================================
RCS file: /fetish/cu/src/touch.c,v
retrieving revision 1.125
diff -p -u -r1.125 touch.c
--- src/touch.c 21 Sep 2004 22:26:42 -0000      1.125
+++ src/touch.c 23 Nov 2004 20:31:53 -0000
@@ -59,9 +59,6 @@ static bool no_create;
 /* (-r) If true, use times from a reference file.  */
 static bool use_ref;
 
-/* (-t) If true, use date supplied on command line in POSIX format.  */
-static bool posix_date;
-
 /* If true, the only thing we have to do is change both the
    modification and access time to the current time, so we don't
    have to own the file, just be able to read and write it.
@@ -127,6 +124,8 @@ touch (const char *file)
   struct stat sbuf;
   int fd = -1;
   int open_errno = 0;
+  struct timespec timespec[2];
+  struct timespec const *t;
 
   if (! no_create)
     {
@@ -142,7 +141,7 @@ touch (const char *file)
        open_errno = errno;
     }
 
-  if (! amtime_now)
+  if (change_times != (CH_ATIME | CH_MTIME))
     {
       /* We're setting only one of the time values.  stat the target to get
         the other one.  If we have the file descriptor already, use fstat.
@@ -165,38 +164,37 @@ touch (const char *file)
        }
     }
 
-  if (fd != -1 && close (fd) < 0)
-    {
-      error (0, errno, _("creating %s"), quote (file));
-      return false;
-    }
-
   if (amtime_now)
     {
-      /* Pass NULL to utime so it will not fail if we just have
+      /* Pass NULL to futimens so it will not fail if we have
         write access to the file, but don't own it.  */
-      ok = (utime (file, NULL) == 0);
+      t = NULL;
     }
   else
     {
-      struct timespec timespec[2];
-      memcpy (timespec, newtime, sizeof timespec);
-
-      if (!(change_times & CH_ATIME))
+      if (change_times & CH_ATIME)
+       timespec[0] = newtime[0];
+      else
        {
          timespec[0].tv_sec = sbuf.st_atime;
          timespec[0].tv_nsec = TIMESPEC_NS (sbuf.st_atim);
        }
 
-      if (!(change_times & CH_MTIME))
+      if (change_times & CH_MTIME)
+       timespec[1] = newtime[1];
+      else
        {
          timespec[1].tv_sec = sbuf.st_mtime;
          timespec[1].tv_nsec = TIMESPEC_NS (sbuf.st_mtim);
        }
 
-      ok = (utimens (file, timespec) == 0);
+      t = timespec;
     }
 
+  ok = (futimens (fd, file, t) == 0);
+  if (fd != -1)
+    ok &= (close (fd) == 0);
+
   if (!ok)
     {
       if (open_errno)
@@ -276,7 +274,8 @@ main (int argc, char **argv)
 
   atexit (close_stdout);
 
-  change_times = no_create = use_ref = posix_date = false;
+  change_times = 0;
+  no_create = use_ref = false;
 
   while ((c = getopt_long (argc, argv, "acd:fmr:t:", longopts, NULL)) != -1)
     {
@@ -292,7 +291,6 @@ main (int argc, char **argv)
 
        case 'd':
          flex_date = optarg;
-         date_set = true;
          break;
 
        case 'f':
@@ -308,10 +306,10 @@ main (int argc, char **argv)
          break;
 
        case 't':
-         posix_date = true;
          if (! posixtime (&newtime[0].tv_sec, optarg,
                           PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS))
-           error (EXIT_FAILURE, 0, _("invalid date format %s"), quote 
(optarg));
+           error (EXIT_FAILURE, 0, _("invalid date format %s"),
+                  quote (optarg));
          newtime[0].tv_nsec = 0;
          newtime[1] = newtime[0];
          date_set = true;
@@ -334,7 +332,7 @@ main (int argc, char **argv)
   if (change_times == 0)
     change_times = CH_ATIME | CH_MTIME;
 
-  if (posix_date && (use_ref || flex_date))
+  if (date_set && (use_ref || flex_date))
     {
       error (0, 0, _("cannot specify times from more than one source"));
       usage (EXIT_FAILURE);
@@ -350,6 +348,7 @@ main (int argc, char **argv)
       newtime[0].tv_nsec = TIMESPEC_NS (ref_stats.st_atim);
       newtime[1].tv_sec = ref_stats.st_mtime;
       newtime[1].tv_nsec = TIMESPEC_NS (ref_stats.st_mtim);
+      date_set = true;
       if (flex_date)
        {
          if (change_times & CH_ATIME)
@@ -357,7 +356,6 @@ main (int argc, char **argv)
          if (change_times & CH_MTIME)
            get_reldate (&newtime[1], flex_date, &newtime[1]);
        }
-      date_set = true;
     }
   else
     {
@@ -365,35 +363,36 @@ main (int argc, char **argv)
        {
          get_reldate (&newtime[0], flex_date, NULL);
          newtime[1] = newtime[0];
+         date_set = true;
        }
     }
 
   /* The obsolete `MMDDhhmm[YY]' form is valid IFF there are
      two or more non-option arguments.  */
-  if (!date_set && 2 <= argc - optind && posix2_version () < 200112)
+  if (!date_set && 2 <= argc - optind && posix2_version () < 200112
+      && posixtime (&newtime[0].tv_sec, argv[optind], PDS_TRAILING_YEAR))
     {
-      if (posixtime (&newtime[0].tv_sec, argv[optind], PDS_TRAILING_YEAR))
-       {
-         newtime[0].tv_nsec = 0;
-         newtime[1] = newtime[0];
-         if (! getenv ("POSIXLY_CORRECT"))
-           {
-             struct tm const *tm = localtime (&newtime[0].tv_sec);
-             error (0, 0,
-                    _("warning: `touch %s' is obsolete; use\
- `touch -t %04ld%02d%02d%02d%02d.%02d'"),
-                    argv[optind],
-                    tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
-                    tm->tm_hour, tm->tm_min, tm->tm_sec);
-           }
+      newtime[0].tv_nsec = 0;
+      newtime[1] = newtime[0];
+      date_set = true;
 
-         optind++;
-         date_set = true;
+      if (! getenv ("POSIXLY_CORRECT"))
+       {
+         struct tm const *tm = localtime (&newtime[0].tv_sec);
+         error (0, 0,
+                _("warning: `touch %s' is obsolete; use "
+                  "`touch -t %04ld%02d%02d%02d%02d.%02d'"),
+                argv[optind],
+                tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
+                tm->tm_hour, tm->tm_min, tm->tm_sec);
        }
+
+      optind++;
     }
+
   if (!date_set)
     {
-      if ((change_times & (CH_ATIME | CH_MTIME)) == (CH_ATIME | CH_MTIME))
+      if (change_times == (CH_ATIME | CH_MTIME))
        amtime_now = true;
       else
        {
Index: lib/utimens.c
===================================================================
RCS file: /fetish/cu/lib/utimens.c,v
retrieving revision 1.2
diff -p -u -r1.2 utimens.c
--- lib/utimens.c       10 Aug 2003 13:29:56 -0000      1.2
+++ lib/utimens.c       23 Nov 2004 20:30:53 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 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
@@ -38,26 +38,67 @@ struct utimbuf
 };
 #endif
 
-/* Set the access and modification time stamps of FILE to be
-   TIMESPEC[0] and TIMESPEC[1], respectively.  */
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+   TIMESPEC[0] and TIMESPEC[1], respectively.
+   FD must be either negative -- in which case it is ignored --
+   or a file descriptor that is open on FILE.
+   If TIMESPEC is null, set the time stamps to the current time.  */
 
 int
-utimens (char const *file, struct timespec const timespec[2])
+futimens (int fd ATTRIBUTE_UNUSED,
+         char const *file, struct timespec const timespec[2])
 {
   /* There's currently no interface to set file timestamps with
      nanosecond resolution, so do the best we can, discarding any
      fractional part of the timestamp.  */
 #if HAVE_WORKING_UTIMES
   struct timeval timeval[2];
-  timeval[0].tv_sec = timespec[0].tv_sec;
-  timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
-  timeval[1].tv_sec = timespec[1].tv_sec;
-  timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
-  return utimes (file, timeval);
+  struct timeval const *t;
+  if (timespec)
+    {
+      timeval[0].tv_sec = timespec[0].tv_sec;
+      timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
+      timeval[1].tv_sec = timespec[1].tv_sec;
+      timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
+      t = timeval;
+    }
+  else
+    t = NULL;
+# if HAVE_FUTIMES
+  if (0 <= fd)
+    return futimes (fd, t);
+# endif
+  return utimes (file, t);
+
 #else
+
   struct utimbuf utimbuf;
-  utimbuf.actime = timespec[0].tv_sec;
-  utimbuf.modtime = timespec[1].tv_sec;
-  return utime (file, &utimbuf);
+  struct utimbuf const *t;
+  if (timespec)
+    {
+      utimbuf.actime = timespec[0].tv_sec;
+      utimbuf.modtime = timespec[1].tv_sec;
+      t = &utimbuf;
+    }
+  else
+    t = NULL;
+  return utime (file, t);
+
 #endif
 }
+
+/* Set the access and modification time stamps of FILE to be
+   TIMESPEC[0] and TIMESPEC[1], respectively.  */
+int
+utimens (char const *file, struct timespec const timespec[2])
+{
+  return futimens (-1, file, timespec);
+}
Index: lib/utimens.h
===================================================================
RCS file: /fetish/cu/lib/utimens.h,v
retrieving revision 1.1
diff -p -u -r1.1 utimens.h
--- lib/utimens.h       9 Aug 2003 18:38:02 -0000       1.1
+++ lib/utimens.h       23 Nov 2004 20:30:53 -0000
@@ -1,2 +1,3 @@
 #include "timespec.h"
+int futimens (int, char const *, struct timespec const [2]);
 int utimens (char const *, struct timespec const [2]);
Index: m4/utimens.m4
===================================================================
RCS file: /fetish/cu/m4/utimens.m4,v
retrieving revision 1.3
diff -p -u -r1.3 utimens.m4
--- m4/utimens.m4       13 Apr 2004 15:28:46 -0000      1.3
+++ m4/utimens.m4       23 Nov 2004 20:30:54 -0000
@@ -1,4 +1,4 @@
-dnl Copyright (C) 2003 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 dnl This file is free software, distributed under the terms of the GNU
 dnl General Public License.  As a special exception to the GNU General
 dnl Public License, this file may be distributed as part of a program
@@ -12,4 +12,5 @@ AC_DEFUN([gl_UTIMENS],
   AC_REQUIRE([gl_FUNC_UTIMES])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_UTIMBUF])
+  AC_CHECK_FUNCS_ONCE(futimes)
 ])




reply via email to

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