[commit: ghc] master: Change how touchy sets the file time (8c7dc71)

Ian Lynagh <[email protected]>
Newsgroups gmane.comp.lang.haskell.cvs.ghc
Message-ID <[email protected]>
Repository : ssh://darcs.haskell.org//srv/darcs/ghc

On branch  : master

http://hackage.haskell.org/trac/ghc/changeset/8c7dc7182803c8e3888e7138958b73ea067fd7e9

>---------------------------------------------------------------

commit 8c7dc7182803c8e3888e7138958b73ea067fd7e9
Author: Ian Lynagh <[email protected]>
Date:   Wed Oct 31 00:53:59 2012 +0100

    Change how touchy sets the file time
    
    Also added a large comment about why we need it

>---------------------------------------------------------------

 utils/touchy/touchy.c |   91 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 86 insertions(+), 5 deletions(-)

diff --git a/utils/touchy/touchy.c b/utils/touchy/touchy.c
index dc4dc8d..93e960d 100644
--- a/utils/touchy/touchy.c
+++ b/utils/touchy/touchy.c
@@ -1,6 +1,5 @@
 /*
- * Simple _utime() wrapper for setting the mod. time on files
- * to the current system time.
+ * Simple 'touch' program for Windows
  *
  */
 #if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_WIN32)
@@ -12,15 +11,85 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <utime.h>
+#include <windows.h>
+
+/*
+With Windows 7 in a virtual box VM on OS X, some very odd things happen
+with dates and time stamps when SSHing into cygwin. e.g. here the
+"Change" time is in the past:
+
+$ date; touch foo; stat foo
+Fri Dec  2 16:58:07 GMTST 2011
+  File: `foo'
+  Size: 0               Blocks: 0          IO Block: 65536  regular
+empty file
+Device: 540aba0bh/1409989131d   Inode: 562949953592977  Links: 1
+Access: (0644/-rw-r--r--)  Uid: ( 1000/     ian)   Gid: (  513/    None)
+Access: 2011-12-02 16:58:07.414457900 +0000
+Modify: 2011-12-02 16:58:07.414457900 +0000
+Change: 2011-12-02 16:58:03.495141800 +0000
+ Birth: 2011-12-02 16:57:57.731469900 +0000
+
+And if we copy such a file, then the copy is older (as determined by the
+"Modify" time) than the original:
+
+$ date; touch foo; stat foo; cp foo bar; stat bar
+Fri Dec  2 16:59:10 GMTST 2011
+  File: `foo'
+  Size: 0               Blocks: 0          IO Block: 65536  regular
+empty file
+Device: 540aba0bh/1409989131d   Inode: 1407374883725128  Links: 1
+Access: (0644/-rw-r--r--)  Uid: ( 1000/     ian)   Gid: (  513/    None)
+Access: 2011-12-02 16:59:10.118457900 +0000
+Modify: 2011-12-02 16:59:10.118457900 +0000
+Change: 2011-12-02 16:59:06.189477700 +0000
+ Birth: 2011-12-02 16:57:57.731469900 +0000
+  File: `bar'
+  Size: 0               Blocks: 0          IO Block: 65536  regular
+empty file
+Device: 540aba0bh/1409989131d   Inode: 281474976882512  Links: 1
+Access: (0644/-rw-r--r--)  Uid: ( 1000/     ian)   Gid: (  513/    None)
+Access: 2011-12-02 16:59:06.394555800 +0000
+Modify: 2011-12-02 16:59:06.394555800 +0000
+Change: 2011-12-02 16:59:06.395532400 +0000
+ Birth: 2011-12-02 16:58:40.921899600 +0000
+
+This means that make thinks that things are out of date when it
+shouldn't, so reinvokes itself repeatedly until the MAKE_RESTARTS
+infinite-recursion test triggers.
+
+The touchy program, like most other programs, creates files with both
+Modify and Change in the past, which is still a little odd, but is
+consistent, so doesn't break make.
+
+We used to use _utime(argv[i],NULL)) to set the file modification times,
+but after a BST -> GMT change this started giving files a modification
+time an hour in the future:
+
+$ date; utils/touchy/dist/build/tmp/touchy testfile; stat testfile
+Tue, Oct 30, 2012 11:33:06 PM
+  File: `testfile'
+  Size: 0               Blocks: 0          IO Block: 65536  regular empty file
+Device: 540aba0bh/1409989131d   Inode: 9851624184986293  Links: 1
+Access: (0755/-rwxr-xr-x)  Uid: ( 1000/     ian)   Gid: (  513/    None)
+Access: 2012-10-31 00:33:06.000000000 +0000
+Modify: 2012-10-31 00:33:06.000000000 +0000
+Change: 2012-10-30 23:33:06.769118900 +0000
+ Birth: 2012-10-30 23:33:06.769118900 +0000
+
+so now we use the Win32 functions GetSystemTimeAsFileTime and SetFileTime.
+*/
 
 int
 main(int argc, char** argv)
 {
-  int rc;
   int i=0;
   int fd;
   int wBitSet = 0;
   struct _stat sb;
+  FILETIME ft;
+  BOOL b;
+  HANDLE hFile;
 
   if (argc == 1) {
     fprintf(stderr, "Usage: %s <files>\n", argv[0]);
@@ -49,8 +118,20 @@ main(int argc, char** argv)
 	}
 	wBitSet = 1;
     }
-    if ( (rc = _utime(argv[i],NULL)) < 0) {
-      fprintf(stderr, "Unable to change mod. time for %s  (%d)\n", argv[i], errno);
+    hFile = CreateFile(argv[i], GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hFile == INVALID_HANDLE_VALUE) {
+       fprintf(stderr, "Unable to open %s\n", argv[i]);
+       continue;
+    }
+    GetSystemTimeAsFileTime(&ft);
+    b = SetFileTime(hFile, (LPFILETIME) NULL, (LPFILETIME) NULL, &ft);
+    if (b == 0) {
+      fprintf(stderr, "Unable to change mod. time for %s\n", argv[i]);
+    }
+    b = CloseHandle(hFile);
+    if (b == 0) {
+      fprintf(stderr, "Closing failed for %s\n", argv[i]);
     }
     if (wBitSet) {
 	/* Turn the file back into a read-only file */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.