Greetings.

Find attached a patch[1] which enhances (f)stat by providing meaningful
values for st_ino & st_dev (allowing Windows to recognize duplicate
files); and fixes a directory traversal bug in FTS (Windows would not
dup the directory file descriptor).

[1] Based on my grep-2.20 port, hope that's okay (you may want -p1 or -p2).

-- 
Jason.
diff -pur grep-2.20/lib/fdopendir.c grep-2-20/lib/fdopendir.c
--- grep-2.20/lib/fdopendir.c   2014-01-02 11:32:05 +1000
+++ grep-2-20/lib/fdopendir.c   2014-07-30 11:50:18 +1000
@@ -115,7 +115,9 @@ fdopendir_with_dup (int fd, int older_du
         }
       else
         {
+#if !(defined _WIN32 || defined __WIN32__) || defined __CYGWIN__
           close (fd);
+#endif
           dir = fd_clone_opendir (dupfd, cwd);
           saved_errno = errno;
           if (! dir)
diff -pur grep-2.20/lib/fstat.c grep-2-20/lib/fstat.c
--- grep-2.20/lib/fstat.c       2014-01-02 11:32:05 +1000
+++ grep-2-20/lib/fstat.c       2014-07-30 11:54:04 +1000
@@ -30,11 +30,29 @@
 # define fstat _fstati64
 #endif
 #undef __need_system_sys_stat_h
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <io.h>
+#endif
 
 static int
 orig_fstat (int fd, struct stat *buf)
 {
-  return fstat (fd, buf);
+  int result = fstat (fd, buf);
+#ifdef WIN32_LEAN_AND_MEAN
+  if (result == 0)
+    {
+      BY_HANDLE_FILE_INFORMATION fi;
+      if (GetFileInformationByHandle ((HANDLE) _get_osfhandle (fd), &fi))
+        {
+          buf->st_ino = LOWORD (fi.dwVolumeSerialNumber);
+          buf->st_dev = (HIWORD (fi.nFileIndexHigh) << 24)
+                        | (fi.nFileIndexLow & 0xFFFFFF);
+        }
+    }
+#endif
+  return result;
 }
 
 /* Specification.  */
diff -pur grep-2.20/lib/fts.c grep-2-20/lib/fts.c
--- grep-2.20/lib/fts.c 2014-05-11 11:45:21 +1000
+++ grep-2-20/lib/fts.c 2014-07-30 11:50:18 +1000
@@ -1399,7 +1399,9 @@ fts_build (register FTS *sp, int type)
         else if (nlinks || type == BREAD) {
                 if (ISSET(FTS_CWDFD))
                   {
+#if !(defined _WIN32 || defined __WIN32__) || defined __CYGWIN__
                     dir_fd = dup (dir_fd);
+#endif
                     if (0 <= dir_fd)
                       set_cloexec_flag (dir_fd, true);
                   }
diff -pur grep-2.20/lib/stat.c grep-2-20/lib/stat.c
--- grep-2.20/lib/stat.c        2014-01-02 11:32:06 +1000
+++ grep-2-20/lib/stat.c        2014-07-30 11:50:18 +1000
@@ -28,6 +28,8 @@
 #undef __need_system_sys_stat_h
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
 # if _GL_WINDOWS_64_BIT_ST_SIZE
 #  undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
 #  define stat _stati64
@@ -134,5 +136,32 @@ rpl_stat (char const *name, struct stat
         }
     }
 #endif /* REPLACE_FUNC_STAT_DIR */
+#ifdef WIN32_LEAN_AND_MEAN
+  if (result == 0)
+    {
+      /* Under Windows, st_dev (32 bits) is the drive number & st_ino (16 bits)
+         is always 0.  The handle file information contains a 32-bit volume
+         serial number (i.e. a device id) with a 64-bit file index (unique file
+         id).  Since the two st values are always tested together, put the
+         lower 16 bits of the serial into st_ino and combine the index values
+         into st_dev (brief testing shows the low word of the high index and
+         the high three digits of the low index are likely 0).  */
+      BY_HANDLE_FILE_INFORMATION fi;
+      HANDLE h = CreateFile (name, 0,
+                             
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
+                             NULL);
+      if (h != INVALID_HANDLE_VALUE)
+        {
+          if (GetFileInformationByHandle (h, &fi))
+            {
+              st->st_ino = LOWORD (fi.dwVolumeSerialNumber);
+              st->st_dev = (HIWORD (fi.nFileIndexHigh) << 24)
+                           | (fi.nFileIndexLow & 0xFFFFFF);
+            }
+          CloseHandle (h);
+        }
+    }
+#endif
   return result;
 }

Reply via email to