This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

allow utimes() to set times of a read only file.


The following patch allow utimes() to set access and
modification times of a read only file. I tested this patch by
`tar', `touch -a', and `touch -m'.

`touch' without any options can't work for read only files,
because it doesn't use utime() but utime_now() defined in
touch.c which set their times by reading and writing their
contents.

--- times.cc-	Tue Aug 24 10:46:25 1999
+++ times.cc	Sat Sep 25 03:58:13 1999
@@ -15,6 +15,7 @@ details. */
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <sys/stat.h>
 #include "winsup.h"
 
 #define FACTOR (0x19db1ded53ea710LL)
@@ -453,20 +454,45 @@ extern "C"
 int
 utimes (const char *path, struct timeval *tvp)
 {
-  int res = 0;
+  int res = -1;
   struct timeval tmp[2];
-  path_conv win32 (path);
+  path_conv win32_path (path);
+  HANDLE h = INVALID_HANDLE_VALUE;
+  int unixattr = -1;
+  DWORD saved_attr;
+  uid_t saved_uid = 0;
+  uid_t saved_gid = 0;
+
+  if (win32_path.error)
+    {
+      set_errno (win32_path.error);
+      goto done;
+    }
+  /* FIXME: This makes utimes on a device succeed always. */
+  if (win32_path.is_device ())
+    {
+      res = 0;
+      goto done;
+    }
 
-  if (win32.error)
+  saved_attr = win32_path.file_attributes ();
+  if (saved_attr == (DWORD)-1)
+    {
+      __seterrno ();
+      goto done;
+    }
+  if (saved_attr & FILE_ATTRIBUTE_READONLY &&
+      !SetFileAttributesA (win32_path.get_win32 (),
+			   saved_attr & ~FILE_ATTRIBUTE_READONLY))
     {
-      set_errno (win32.error);
-      syscall_printf ("-1 = utimes (%s, %x)", path, tvp);
-      return -1;
+      __seterrno ();
+      goto done;
     }
 
   /* MSDN suggests using FILE_FLAG_BACKUP_SEMANTICS for accessing
      the times of directories.  FIXME: what about Win95??? */
-  HANDLE h = CreateFileA (win32.get_win32 (),
+retry:
+  h = CreateFileA (win32_path.get_win32 (),
 			  GENERIC_WRITE,
 			  FILE_SHARE_READ | FILE_SHARE_WRITE,
 			  &sec_none_nih,
@@ -476,54 +502,71 @@ utimes (const char *path, struct timeval
 
   if (h == INVALID_HANDLE_VALUE)
     {
-      if ((res = GetFileAttributes (win32.get_win32 ())) != -1 &&
-		(res & FILE_ATTRIBUTE_DIRECTORY))
+      if (allow_ntsec && win32_path.has_acls () &&
+	  unixattr == -1 && GetLastError () == ERROR_ACCESS_DENIED)
 	{
-	  /* What we can do with directories more? */
-	  res = 0;
+	  unixattr = 0;
+	  if (get_file_attribute (TRUE, win32_path.get_win32 (), &unixattr))
+	    {
+	      unixattr = -1;
+	      goto recover;
+	    }
+	  saved_uid = get_file_owner (TRUE, win32_path.get_win32 ());
+	  saved_gid = get_file_group (TRUE, win32_path.get_win32 ());
+	  if (set_file_attribute (TRUE, win32_path.get_win32 (),
+				  saved_uid, saved_gid,
+				  unixattr | S_IWUSR))
+	    {
+	      unixattr = -1;
+	      goto recover;
+	    }
+	  goto retry;
 	}
-      else
+      if ((res = GetFileAttributes (win32_path.get_win32 ())) != -1 &&
+	  (res & FILE_ATTRIBUTE_DIRECTORY))
 	{
-	  res = -1;
-	  __seterrno ();
+	  /* What we can do with directories more? */
+	  res = 0;
+	  goto recover;
 	}
+      __seterrno ();
+      goto recover;
     }
-  else
+  if (tvp == 0)
     {
-      if (tvp == 0)
-	{
-	  gettimeofday (&tmp[0], 0);
-	  tmp[1] = tmp[0];
-	  tvp = tmp;
-	}
+      gettimeofday (&tmp[0], 0);
+      tmp[1] = tmp[0];
+      tvp = tmp;
+    }
 
-      FILETIME lastaccess;
-      FILETIME lastwrite;
+  FILETIME lastaccess;
+  FILETIME lastwrite;
 
-      timeval_to_filetime (tvp + 0, &lastaccess);
-      timeval_to_filetime (tvp + 1, &lastwrite);
+  timeval_to_filetime (tvp + 0, &lastaccess);
+  timeval_to_filetime (tvp + 1, &lastwrite);
 
-      debug_printf ("incoming lastaccess %08x %08x",
-		   tvp->tv_sec,
-		   tvp->tv_usec);
+  debug_printf ("incoming lastaccess %08x %08x",
+		tvp->tv_sec,
+		tvp->tv_usec);
 
 //      dump_filetime (lastaccess);
 //      dump_filetime (lastwrite);
 
-      /* FIXME: SetFileTime needs a handle with a write lock
-	 on the file whose time is being modified.  So calls to utime()
-	 fail for read only files.  */
+  if (!SetFileTime (h, 0, &lastaccess, &lastwrite))
+    __seterrno ();
+  else
+    res = 0;
+  CloseHandle (h);
 
-      if (!SetFileTime (h, 0, &lastaccess, &lastwrite))
-	{
-	  __seterrno ();
-	  res = -1;
-	}
-      else
-	res = 0;
-      CloseHandle (h);
-    }
+recover:
+  if (saved_attr & FILE_ATTRIBUTE_READONLY)
+    SetFileAttributesA (win32_path.get_win32 (), saved_attr);
+
+  if (unixattr != -1)
+    set_file_attribute (TRUE, win32_path.get_win32 (),
+			saved_uid, saved_gid, unixattr);
 
+done:
   syscall_printf ("%d = utimes (%s, %x); (h%d)",
 		  res, path, tvp, h);
   return res;

____
  | AIST      Kazuhiro Fujieda <fujieda@jaist.ac.jp>
  | HOKURIKU  School of Information Science
o_/ 1990      Japan Advanced Institute of Science and Technology

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]