diff -Naur a/build-aux/compile b/build-aux/compile
--- a/build-aux/compile	2014-07-19 02:02:06.000000000 +0400
+++ b/build-aux/compile	2014-07-20 20:19:52.863800000 +0400
@@ -53,7 +53,7 @@
 	  MINGW*)
 	    file_conv=mingw
 	    ;;
-	  CYGWIN*)
+	  CYGWIN* | MSYS*)
 	    file_conv=cygwin
 	    ;;
 	  *)
@@ -67,7 +67,7 @@
 	mingw/*)
 	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
 	  ;;
-	cygwin/*)
+	cygwin/* | msys/*)
 	  file=`cygpath -m "$file" || echo "$file"`
 	  ;;
 	wine/*)
diff -Naur a/gnulib-tests/test-copy-acl.sh b/gnulib-tests/test-copy-acl.sh
--- a/gnulib-tests/test-copy-acl.sh	2013-12-04 18:53:33.000000000 +0400
+++ b/gnulib-tests/test-copy-acl.sh	2014-07-20 20:19:52.895000000 +0400
@@ -128,7 +128,7 @@
   # the programs.
   # func_test_same_acls file1 file2
   case $acl_flavor in
-    linux | cygwin | freebsd | solaris)
+    linux | cygwin | msys | freebsd | solaris)
       func_test_same_acls ()
       {
         getfacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
@@ -302,7 +302,7 @@
 
         ;;
 
-      cygwin)
+      cygwin | msys)
 
         # Set an ACL for a group.
         setfacl -m group:0:1 tmpfile0
diff -Naur a/gnulib-tests/test-file-has-acl.sh b/gnulib-tests/test-file-has-acl.sh
--- a/gnulib-tests/test-file-has-acl.sh	2013-12-04 18:53:33.000000000 +0400
+++ b/gnulib-tests/test-file-has-acl.sh	2014-07-20 20:19:52.910600000 +0400
@@ -247,7 +247,7 @@
         fi
         ;;
 
-      cygwin)
+      cygwin | msys)
 
         # Set an ACL for a group.
         if setfacl -m group:0:1 tmpfile0; then
diff -Naur a/gnulib-tests/test-set-mode-acl.sh b/gnulib-tests/test-set-mode-acl.sh
--- a/gnulib-tests/test-set-mode-acl.sh	2013-12-04 18:53:33.000000000 +0400
+++ b/gnulib-tests/test-set-mode-acl.sh	2014-07-20 20:19:52.910600000 +0400
@@ -177,7 +177,7 @@
           linux | freebsd | solaris)
             setfacl -m user:$auid:1 tmpfile0
             ;;
-          cygwin)
+          cygwin | msys)
             setfacl -m group:0:1 tmpfile0
             ;;
           hpux)
diff -Naur a/install.exe.manifest b/install.exe.manifest
--- a/install.exe.manifest	1970-01-01 03:00:00.000000000 +0300
+++ b/install.exe.manifest	2014-07-20 20:19:52.910600000 +0400
@@ -0,0 +1,11 @@
+﻿<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3">
+    <v3:security>
+      <v3:requestedPrivileges>
+        <v3:requestedExecutionLevel level="asInvoker" />
+      </v3:requestedPrivileges>
+    </v3:security>
+  </v3:trustInfo>
+</assembly>
+
diff -Naur a/src/install.manifest b/src/install.manifest
--- a/src/install.manifest	1970-01-01 03:00:00.000000000 +0300
+++ b/src/install.manifest	2014-07-20 20:19:47.591000000 +0400
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <assemblyIdentity version="1.0.0.0"
+     processorArchitecture="x86"
+     name="GNU.coreutils.install"
+     type="win32"/>
+
+  <!-- Identify the application security requirements. -->
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+</assembly>
diff -Naur a/src/install.rc b/src/install.rc
--- a/src/install.rc	1970-01-01 03:00:00.000000000 +0300
+++ b/src/install.rc	2014-07-20 20:19:47.606600000 +0400
@@ -0,0 +1 @@
+1 24 install.manifest
--- a/Makefile.in.orig	2018-09-16 13:23:25.153210900 +0200
+++ a/Makefile.in	2018-09-16 13:39:17.989133200 +0200
@@ -989,7 +989,7 @@
 	lib/openat-proc.c lib/backupfile.c lib/backup-rename.c \
 	lib/backup-find.c lib/base32.h lib/base32.c lib/base64.h \
 	lib/base64.c lib/binary-io.h lib/binary-io.c lib/bitrotate.h \
-	lib/bitrotate.c lib/buffer-lcm.c lib/buffer-lcm.h \
+	lib/bitrotate.c lib/buffer-lcm.c lib/buffer-lcm.h lib/cygwin.c lib/cygwin.h \
 	lib/c-ctype.h lib/c-ctype.c lib/c-strcase.h lib/c-strcasecmp.c \
 	lib/c-strncasecmp.c lib/c-strtod.c lib/c-strtold.c \
 	lib/canon-host.c lib/canonicalize.c lib/careadlinkat.c \
@@ -1078,7 +1078,7 @@
 	lib/backupfile.$(OBJEXT) lib/backup-find.$(OBJEXT) \
 	lib/base32.$(OBJEXT) lib/base64.$(OBJEXT) \
 	lib/binary-io.$(OBJEXT) lib/bitrotate.$(OBJEXT) \
-	lib/buffer-lcm.$(OBJEXT) lib/c-ctype.$(OBJEXT) \
+	lib/buffer-lcm.$(OBJEXT) lib/cygwin.$(OBJEXT) lib/c-ctype.$(OBJEXT) \
 	lib/c-strcasecmp.$(OBJEXT) lib/c-strncasecmp.$(OBJEXT) \
 	lib/c-strtod.$(OBJEXT) lib/c-strtold.$(OBJEXT) \
 	lib/canon-host.$(OBJEXT) lib/canonicalize.$(OBJEXT) \
@@ -3930,6 +3930,7 @@
 WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@
 WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@
 WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@
+WINDRES = windres
 WINT_T_SUFFIX = @WINT_T_SUFFIX@
 XGETTEXT = @XGETTEXT@
 XGETTEXT_015 = @XGETTEXT_015@
@@ -5309,7 +5310,7 @@
 	lib/backupfile.c lib/backup-find.c lib/base32.h lib/base32.c \
 	lib/base64.h lib/base64.c lib/binary-io.h lib/binary-io.c \
 	lib/bitrotate.h lib/bitrotate.c lib/buffer-lcm.c \
-	lib/buffer-lcm.h lib/c-ctype.h lib/c-ctype.c lib/c-strcase.h \
+	lib/buffer-lcm.h lib/cygwin.c lib/cygwin.h lib/c-ctype.c lib/c-strcase.h \
 	lib/c-strcasecmp.c lib/c-strncasecmp.c lib/c-strtod.c \
 	lib/c-strtold.c lib/canon-host.c lib/canonicalize.c \
 	lib/careadlinkat.c lib/chmodat.c lib/chownat.c lib/cl-strtod.c \
@@ -6097,6 +6098,8 @@
 	lib/$(DEPDIR)/$(am__dirstamp)
 lib/buffer-lcm.$(OBJEXT): lib/$(am__dirstamp) \
 	lib/$(DEPDIR)/$(am__dirstamp)
+lib/cygwin.$(OBJEXT): lib/$(am__dirstamp) \
+	lib/$(DEPDIR)/$(am__dirstamp)
 lib/c-ctype.$(OBJEXT): lib/$(am__dirstamp) \
 	lib/$(DEPDIR)/$(am__dirstamp)
 lib/c-strcasecmp.$(OBJEXT): lib/$(am__dirstamp) \
@@ -9110,9 +9113,9 @@
 src/src_ginstall-selinux.$(OBJEXT): src/$(am__dirstamp) \
 	src/$(DEPDIR)/$(am__dirstamp)
 
-src/ginstall$(EXEEXT): $(src_ginstall_OBJECTS) $(src_ginstall_DEPENDENCIES) $(EXTRA_src_ginstall_DEPENDENCIES) src/$(am__dirstamp)
+src/ginstall$(EXEEXT): $(src_ginstall_OBJECTS) src/src_ginstall-manifest.res $(src_ginstall_DEPENDENCIES) $(EXTRA_src_ginstall_DEPENDENCIES) src/$(am__dirstamp)
 	@rm -f src/ginstall$(EXEEXT)
-	$(AM_V_CCLD)$(LINK) $(src_ginstall_OBJECTS) $(src_ginstall_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(src_ginstall_OBJECTS) src/src_ginstall-manifest.res $(src_ginstall_LDADD) $(LIBS)
 src/groups.$(OBJEXT): src/$(am__dirstamp) \
 	src/$(DEPDIR)/$(am__dirstamp)
 src/group-list.$(OBJEXT): src/$(am__dirstamp) \
@@ -10029,6 +10031,9 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_libsinglebin_fold_a_CFLAGS) $(CFLAGS) -c -o src/libsinglebin_fold_a-fold.obj `if test -f 'src/fold.c'; then $(CYGPATH_W) 'src/fold.c'; else $(CYGPATH_W) '$(srcdir)/src/fold.c'; fi`
 
+src/src_ginstall-manifest.res: src/install.rc src/install.manifest
+	$(WINDRES) --input $< --output $@ --output-format=coff
+
 src/libsinglebin_ginstall_a-install.o: src/install.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libsinglebin_ginstall_a_CPPFLAGS) $(CPPFLAGS) $(src_libsinglebin_ginstall_a_CFLAGS) $(CFLAGS) -MT src/libsinglebin_ginstall_a-install.o -MD -MP -MF src/$(DEPDIR)/libsinglebin_ginstall_a-install.Tpo -c -o src/libsinglebin_ginstall_a-install.o `test -f 'src/install.c' || echo '$(srcdir)/'`src/install.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/$(DEPDIR)/libsinglebin_ginstall_a-install.Tpo src/$(DEPDIR)/libsinglebin_ginstall_a-install.Po
--- a/lib/cygwin.c	1969-12-31 18:00:00.000000000 -0600
+++ b/lib/cygwin.c	2017-02-03 13:32:48.725613200 -0600
@@ -0,0 +1,73 @@
+/* cygwin.c - helper functions unique to Cygwin
+
+   Copyright (C) 2005, 2006, 2008, 2011 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 Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Eric Blake.  */
+
+#include <config.h>
+
+#include "cygwin.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Return -1 if PATH is not found, 0 if PATH will not have .exe
+   appended (it is possible that a PATH that does not exist still
+   returns 0 instead of -1, or fails for a PATH that exists but cannot
+   be stat'ed), and positive if PATH has ".exe" automatically appended
+   by cygwin (1 if PATH is a symlink, 2 otherwise).  Won't change errno.  */
+
+int
+cygwin_spelling (char const *path)
+{
+  int saved_errno = errno;
+  int result = 0; /* Start with assumption that PATH is okay.  */
+  size_t len;
+  struct stat st1;
+  struct stat st2;
+  char *path_exe;
+
+  /* If PATH will cause EINVAL or ENAMETOOLONG, treat it as missing.  */
+  if (! path || ! *path)
+    return -1;
+  if (PATH_MAX < (len = strlen (path)))
+    return -1;
+  /* Don't change spelling if there is a trailing `/' or '.exe'.  */
+  if (path[len - 1] == '/'
+      || (len > 4 && !strcasecmp (&path[len - 4], ".exe")))
+    return 0;
+  if (lstat (path, &st1) < 0)
+    {
+      errno = saved_errno;
+      return -1;
+    }
+  if (S_ISDIR(st1.st_mode))
+    {
+      errno = saved_errno;
+      return 0;
+    }
+  path_exe = malloca (len + 5); /* adding ".exe" and NUL.  */
+  strcat (stpcpy (path_exe, path), ".exe");
+  if (lstat (path_exe, &st2) == 0 && st1.st_ino == st2.st_ino)
+    result = 1 + !S_ISLNK(st1.st_mode);
+  freea (path_exe);
+
+  errno = saved_errno;
+  return result;
+}
--- a/lib/cygwin.h	1969-12-31 18:00:00.000000000 -0600
+++ b/lib/cygwin.h	2017-02-03 13:32:48.725613200 -0600
@@ -0,0 +1,38 @@
+/* cygwin.h - helper functions unique to Cygwin
+
+   Copyright (C) 2005, 2006, 2008, 2010, 2011 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 Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Eric Blake.  */
+
+#ifndef CYGWIN_H
+# define CYGWIN_H 1
+
+#include "malloca.h"
+
+int cygwin_spelling (char const *);
+
+/* Append ".exe" to char *__NAME_ORIG, where __NAME is either NULL or
+   between __NAME_ORIG and the nul terminator.  Both params will be
+   evaluated more than once and assigned the new value.  The user must
+   later call freea(__NAME).  */
+#define CYGWIN_APPEND_EXE(__name, __name_orig)                          \
+  __name_orig = __name =                                                \
+    strcat (strcpy (malloca (strchr (__name ? __name : __name_orig, '\0') \
+                             - (__name_orig) + 5),                      \
+                    __name_orig), ".exe")
+
+#endif /* CYGWIN_H */
--- a/lib/hash-pjw.c	2016-07-15 14:47:39.000000000 -0500
+++ b/lib/hash-pjw.c	2017-02-03 13:32:48.725613200 -0600
@@ -19,6 +19,7 @@
 
 #include "hash-pjw.h"
 
+#include <ctype.h>
 #include <limits.h>
 
 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
@@ -38,3 +39,16 @@ hash_pjw (const void *x, size_t tablesiz
 
   return h % tablesize;
 }
+
+/* Likewise, but case-insensitive.  */
+size_t
+hash_pjw_case (const void *x, size_t tablesize)
+{
+  const unsigned char *s;
+  size_t h = 0;
+
+  for (s = x; *s; s++)
+    h = tolower (*s) + ((h << 9) | (h >> (SIZE_BITS - 9)));
+
+  return h % tablesize;
+}
--- a/lib/hash-pjw.h	2016-07-15 14:47:39.000000000 -0500
+++ b/lib/hash-pjw.h	2017-02-03 13:32:48.725613200 -0600
@@ -21,3 +21,4 @@
    The result is platform dependent: it depends on the size of the 'size_t'
    type and on the signedness of the 'char' type.  */
 extern size_t hash_pjw (void const *x, size_t tablesize) _GL_ATTRIBUTE_PURE;
+extern size_t hash_pjw_case (void const *x, size_t tablesize) _GL_ATTRIBUTE_PURE;
--- a/lib/hash-triple.c	2016-07-15 14:47:39.000000000 -0500
+++ b/lib/hash-triple.c	2017-02-03 13:32:48.725613200 -0600
@@ -34,7 +34,13 @@ size_t
 triple_hash (void const *x, size_t table_size)
 {
   struct F_triple const *p = x;
+#ifndef __CYGWIN__
   size_t tmp = hash_pjw (p->name, table_size);
+#else
+  /* Hash case-insensitively, to force collisions on names that differ only
+     by case; copy.c can then account for case-insensitive renames. */
+  size_t tmp = hash_pjw_case (p->name, table_size);
+#endif
 
   /* Ignoring the device number here should be fine.  */
   return (tmp ^ p->st_ino) % table_size;
--- a/lib/local.mk	2012-11-13 07:51:53.000000000 -0600
+++ b/lib/local.mk	2017-02-03 13:32:48.725613200 -0600
@@ -3,3 +3,6 @@ include lib/gnulib.mk
 # Allow "make distdir" to succeed before "make all" has run.
 dist-hook: $(noinst_LIBRARIES)
 .PHONY: dist-hook
+
+# Hook in cygwin helper
+lib_libcoreutils_a_SOURCES += lib/cygwin.c lib/cygwin.h
--- a/lib/root-dev-ino.c	2016-03-09 04:15:39.000000000 -0600
+++ b/lib/root-dev-ino.c	2017-02-03 13:32:48.725613200 -0600
@@ -25,13 +25,17 @@
 /* Call lstat to get the device and inode numbers for '/'.
    Upon failure, return NULL.  Otherwise, set the members of
    *ROOT_D_I accordingly and return ROOT_D_I.  */
-struct dev_ino *
-get_root_dev_ino (struct dev_ino *root_d_i)
+struct root_dev_ino *
+get_root_dev_ino (struct root_dev_ino *root_d_i)
 {
   struct stat statbuf;
   if (lstat ("/", &statbuf))
     return NULL;
-  root_d_i->st_ino = statbuf.st_ino;
-  root_d_i->st_dev = statbuf.st_dev;
+  root_d_i->single_slash.st_ino = statbuf.st_ino;
+  root_d_i->single_slash.st_dev = statbuf.st_dev;
+  if (lstat ("//", &statbuf))
+    return NULL;
+  root_d_i->double_slash.st_ino = statbuf.st_ino;
+  root_d_i->double_slash.st_dev = statbuf.st_dev;
   return root_d_i;
 }
--- a/lib/root-dev-ino.h	2016-03-09 04:15:39.000000000 -0600
+++ b/lib/root-dev-ino.h	2017-02-03 13:32:48.741217700 -0600
@@ -21,19 +21,26 @@
 # include "dev-ino.h"
 # include "same-inode.h"
 
-struct dev_ino *
-get_root_dev_ino (struct dev_ino *root_d_i);
+struct root_dev_ino
+{
+  struct dev_ino single_slash;
+  struct dev_ino double_slash;
+};
+
+struct root_dev_ino *
+get_root_dev_ino (struct root_dev_ino *root_d_i);
 
 /* These macros are common to the programs that support the
    --preserve-root and --no-preserve-root options.  */
 
 # define ROOT_DEV_INO_CHECK(Root_dev_ino, Dir_statbuf) \
-    (Root_dev_ino && SAME_INODE (*Dir_statbuf, *Root_dev_ino))
+  (Root_dev_ino && (SAME_INODE (*Dir_statbuf, (Root_dev_ino)->single_slash) \
+                    || SAME_INODE (*Dir_statbuf, (Root_dev_ino)->double_slash)))
 
 # define ROOT_DEV_INO_WARN(Dirname)					\
   do									\
     {									\
-      if (STREQ (Dirname, "/"))						\
+      if (STREQ (Dirname, "/") || STREQ (Dirname, "//"))                \
         error (0, 0, _("it is dangerous to operate recursively on %s"),	\
                quoteaf (Dirname));					\
       else								\
--- a/lib/same.c	2018-05-14 06:20:31.000000000 +0200
+++ b/lib/same.c	2018-09-16 13:54:23.478109900 +0200
@@ -41,6 +41,13 @@
 #include "error.h"
 #include "same-inode.h"
 
+#if __CYGWIN__
+# include <sys/cygwin.h>
+# include "cygwin.h"
+# include "malloca.h"
+# include "memcasecmp.h"
+#endif
+
 #ifndef MIN
 # define MIN(a, b) ((a) < (b) ? (a) : (b))
 #endif
@@ -79,6 +86,45 @@
     (source_baselen == dest_baselen
      && memcmp (source_basename, dest_basename, dest_baselen) == 0);
   bool compare_dirs = identical_basenames;
+#if __CYGWIN__
+  /* If two names differ case-insensitively by only an '.exe' suffix,
+     do some sleuthing to see if .exe magic matters on the shorter
+     name.  Swapping the longer name to dest avoids duplication.  */
+  if (source_baselen == dest_baselen + 4)
+    {
+      char const *tmp_basename = source_basename;
+      size_t tmp_baselen = source_baselen;
+      source_basename = dest_basename;
+      source_baselen = dest_baselen;
+      dest_basename = tmp_basename;
+      dest_baselen = tmp_baselen;
+    }
+  if (source_baselen + 4 == dest_baselen
+      && !memcasecmp (dest_basename - 4, ".exe", 4)
+      && !memcasecmp (source_basename, dest_basename, source_baselen)
+      && 0 < cygwin_spelling(source))
+    dest_baselen -= 4;
+  /* Some, but not all, files are case-insensitive (depending on mount
+     options, CYGWIN=case settings, and virtual file systems).  Do
+     some sleuthing to decide whether case-insensitivity matters.  */
+  if (! compare_dirs && source_baselen == dest_baselen)
+    {
+      ssize_t wsrclen = cygwin_conv_path (CCP_POSIX_TO_WIN_W,
+                                          source, NULL, 0);
+      ssize_t wdstlen = cygwin_conv_path (CCP_POSIX_TO_WIN_W,
+                                          dest, NULL, 0);
+      char *wsrc = malloca (wsrclen);
+      char *wdst = malloca (wdstlen);
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, source, wsrc, wsrclen))
+        error (EXIT_FAILURE, errno, "unable to convert path name %s", source);
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, dest, wdst, wdstlen))
+        error (EXIT_FAILURE, errno, "unable to convert path name %s", dest);
+      if (wsrclen == wdstlen && memcasecmp (wsrc, wdst, wsrclen) == 0)
+        compare_dirs = true;
+      freea (wsrc);
+      freea (wdst);
+    }
+#endif /* __CYGWIN__ */
   bool same = false;
 
 #if CHECK_TRUNCATION
--- a/src/chcon.c	2016-11-06 16:15:29.000000000 -0600
+++ b/src/chcon.c	2017-02-03 13:32:48.741217700 -0600
@@ -48,7 +48,7 @@ static bool verbose;
 
 /* Pointer to the device and inode numbers of '/', when --recursive.
    Otherwise NULL.  */
-static struct dev_ino *root_dev_ino;
+static struct root_dev_ino *root_dev_ino;
 
 /* The name of the context file is being given. */
 static char const *specified_context;
@@ -570,7 +570,7 @@ main (int argc, char **argv)
 
   if (recurse && preserve_root)
     {
-      static struct dev_ino dev_ino_buf;
+      static struct root_dev_ino dev_ino_buf;
       root_dev_ino = get_root_dev_ino (&dev_ino_buf);
       if (root_dev_ino == NULL)
         die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
--- a/src/chgrp.c	2016-11-06 16:15:29.000000000 -0600
+++ b/src/chgrp.c	2017-02-03 13:32:48.741217700 -0600
@@ -301,7 +301,7 @@ main (int argc, char **argv)
 
   if (chopt.recurse && preserve_root)
     {
-      static struct dev_ino dev_ino_buf;
+      static struct root_dev_ino dev_ino_buf;
       chopt.root_dev_ino = get_root_dev_ino (&dev_ino_buf);
       if (chopt.root_dev_ino == NULL)
         die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
--- a/src/chmod.c	2016-11-06 16:15:29.000000000 -0600
+++ b/src/chmod.c	2017-02-03 13:32:48.741217700 -0600
@@ -81,7 +81,7 @@ static enum Verbosity verbosity = V_off;
 
 /* Pointer to the device and inode numbers of '/', when --recursive.
    Otherwise NULL.  */
-static struct dev_ino *root_dev_ino;
+static struct root_dev_ino *root_dev_ino;
 
 /* For long options that have no equivalent short option, use a
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
@@ -552,7 +552,7 @@ main (int argc, char **argv)
 
   if (recurse && preserve_root)
     {
-      static struct dev_ino dev_ino_buf;
+      static struct root_dev_ino dev_ino_buf;
       root_dev_ino = get_root_dev_ino (&dev_ino_buf);
       if (root_dev_ino == NULL)
         die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
--- a/src/chown-core.h	2016-03-09 04:15:39.000000000 -0600
+++ b/src/chown-core.h	2017-02-03 13:32:48.741217700 -0600
@@ -50,7 +50,7 @@ struct Chown_option
 
   /* Pointer to the device and inode numbers of '/', when --recursive.
      Need not be freed.  Otherwise NULL.  */
-  struct dev_ino *root_dev_ino;
+  struct root_dev_ino *root_dev_ino;
 
   /* This corresponds to the --dereference (opposite of -h) option.  */
   bool affect_symlink_referent;
--- a/src/chown.c	2016-11-06 16:15:29.000000000 -0600
+++ b/src/chown.c	2017-02-03 13:32:48.741217700 -0600
@@ -313,7 +313,7 @@ main (int argc, char **argv)
 
   if (chopt.recurse && preserve_root)
     {
-      static struct dev_ino dev_ino_buf;
+      static struct root_dev_ino dev_ino_buf;
       chopt.root_dev_ino = get_root_dev_ino (&dev_ino_buf);
       if (chopt.root_dev_ino == NULL)
         die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
--- a/src/chroot.c	2016-11-06 16:15:29.000000000 -0600
+++ b/src/chroot.c	2017-02-03 13:32:48.741217700 -0600
@@ -171,7 +171,8 @@ static bool
 is_root (const char* dir)
 {
   char *resolved = canonicalize_file_name (dir);
-  bool is_res_root = resolved && STREQ ("/", resolved);
+  bool is_res_root = resolved && (STREQ ("/", resolved)
+				  || STREQ ( "//", resolved));
   free (resolved);
   return is_res_root;
 }
--- a/src/cksum.c	2016-11-06 16:15:29.000000000 -0600
+++ b/src/cksum.c	2017-02-03 13:32:48.741217700 -0600
@@ -301,6 +301,9 @@ main (int argc, char **argv)
 
   have_read_stdin = false;
 
+  if (O_BINARY)
+    xset_binary_mode (STDIN_FILENO, O_BINARY);
+
   if (optind == argc)
     ok = cksum ("-", false);
   else
--- a/src/dd.c	2016-11-09 15:11:35.000000000 -0600
+++ b/src/dd.c	2017-02-03 13:32:48.741217700 -0600
@@ -38,6 +38,10 @@
 #include "xstrtol.h"
 #include "xtime.h"
 
+#ifdef __CYGWIN__
+# include <io.h>
+#endif
+
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "dd"
 
@@ -2024,6 +2028,13 @@
 static void
 set_fd_flags (int fd, int add_flags, char const *name)
 {
+#if __CYGWIN__
+  /* Cygwin does not allow fcntl to set the mode.  */
+  int mode_flags = add_flags & (O_BINARY | O_TEXT);
+  add_flags &= ~(O_BINARY | O_TEXT);
+  if (mode_flags && setmode (fd, mode_flags) == -1)
+    error (EXIT_FAILURE, errno, _("setting flags for %s"), quote (name));
+#endif /* __CYGWIN__ */
   /* Ignore file creation flags that are no-ops on file descriptors.  */
   add_flags &= ~ (O_NOCTTY | O_NOFOLLOW);
 
@@ -2418,6 +2429,8 @@
     }
   else
     {
+      if ((input_flags & (O_BINARY | O_TEXT)) == 0)
+	input_flags |= O_BINARY;
       if (ifd_reopen (STDIN_FILENO, input_file, O_RDONLY | input_flags, 0) < 0)
         die (EXIT_FAILURE, errno, _("failed to open %s"),
              quoteaf (input_file));
@@ -2441,6 +2454,8 @@
            | (conversions_mask & C_NOCREAT ? 0 : O_CREAT)
            | (conversions_mask & C_EXCL ? O_EXCL : 0)
            | (seek_records || (conversions_mask & C_NOTRUNC) ? 0 : O_TRUNC));
+      if ((opts & (O_BINARY | O_TEXT)) == 0)
+	opts |= O_BINARY;
 
       /* Open the output file with *read* access only if we might
          need to read to satisfy a 'seek=' request.  If we can't read
--- a/src/install.c	2016-11-28 10:17:17.000000000 -0600
+++ b/src/install.c	2017-02-03 13:32:48.741217700 -0600
@@ -45,6 +45,10 @@
 #include "utimens.h"
 #include "xstrtol.h"
 
+#ifdef __CYGWIN__
+# include "cygwin.h"
+#endif
+
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "install"
 
@@ -556,6 +560,16 @@ strip (char const *name)
       error (0, errno, _("fork system call failed"));
       break;
     case 0:			/* Child. */
+#if __CYGWIN__
+      {
+	/* Check for .exe here, since strip doesn't.  */
+	char *p;
+	if (((p = strchr (name, '\0') - 4) <= name
+	     || strcasecmp (p, ".exe") != 0)
+	    && 0 < cygwin_spelling (name))
+          CYGWIN_APPEND_EXE (p, name);
+      }
+#endif /* __CYGWIN__ */
       execlp (strip_program, strip_program, name, NULL);
       die (EXIT_FAILURE, errno, _("cannot run %s"), quoteaf (strip_program));
     default:			/* Parent. */
--- a/src/ls.c	2016-11-22 14:04:32.000000000 -0600
+++ b/src/ls.c	2017-02-03 13:32:48.741217700 -0600
@@ -122,6 +122,10 @@
 # include <sys/capability.h>
 #endif
 
+#ifdef __CYGWIN__
+# include "cygwin.h"
+#endif
+
 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
                       : (ls_mode == LS_MULTI_COL \
                          ? "dir" : "vdir"))
@@ -783,6 +787,11 @@
     N_("%b %e %H:%M")
   };
 
+#if __CYGWIN__
+/* Whether .exe should be appended to command-line args as needed.  */
+static bool append_exe;
+#endif /* __CYGWIN__ */
+
 /* The set of signals that are caught.  */
 
 static sigset_t caught_signals;
@@ -818,6 +827,9 @@
 enum
 {
   AUTHOR_OPTION = CHAR_MAX + 1,
+#ifdef __CYGWIN__
+  APPEND_EXE_OPTION,
+#endif
   BLOCK_SIZE_OPTION,
   COLOR_OPTION,
   DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION,
@@ -881,6 +893,9 @@
   {"block-size", required_argument, NULL, BLOCK_SIZE_OPTION},
   {"context", no_argument, 0, 'Z'},
   {"author", no_argument, NULL, AUTHOR_OPTION},
+#ifdef __CYGWIN__
+  {"append-exe", no_argument, NULL, APPEND_EXE_OPTION},
+#endif
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -2099,6 +2114,12 @@
           print_scontext = true;
           break;
 
+#ifdef __CYGWIN__
+	case APPEND_EXE_OPTION:
+	  append_exe = true;
+	  break;
+#endif
+
         case_GETOPT_HELP_CHAR;
 
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -3110,6 +3131,12 @@
   uintmax_t blocks = 0;
   struct fileinfo *f;
 
+#ifdef __CYGWIN__
+  char *name_alt = NULL;
+  if (command_line_arg && append_exe && 0 < cygwin_spelling (name))
+    CYGWIN_APPEND_EXE (name_alt, name);
+#endif /* __CYGWIN__ */
+
   /* An inode value prior to gobble_file necessarily came from readdir,
      which is not used for command line arguments.  */
   assert (! command_line_arg || inode == NOT_AN_INODE_NUMBER);
@@ -3240,11 +3267,19 @@
           file_failure (command_line_arg,
                         _("cannot access %s"), full_name);
           if (command_line_arg)
-            return 0;
+	    {
+#ifdef __CYGWIN__
+	      freea (name_alt);
+#endif
+	      return 0;
+	    }
 
           f->name = xstrdup (name);
           cwd_n_used++;
 
+#ifdef __CYGWIN__
+	  freea (name_alt);
+#endif
           return 0;
         }
 
@@ -3433,6 +3468,9 @@
   f->name = xstrdup (name);
   cwd_n_used++;
 
+#ifdef __CYGWIN__
+  freea (name_alt);
+#endif
   return blocks;
 }
 
@@ -5277,6 +5315,11 @@
   -1                         list one file per line.  Avoid '\\n' with -q or -b\
 \n\
 "), stdout);
+#if __CYGWIN__
+      fputs (_("\
+      --append-exe           append .exe if cygwin magic was needed\n\
+"), stdout);
+#endif /* __CYGWIN__ */
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
       emit_size_note ();
--- a/src/md5sum.c	2016-11-22 14:04:32.000000000 -0600
+++ b/src/md5sum.c	2017-02-03 13:32:48.741217700 -0600
@@ -1039,6 +1039,9 @@ main (int argc, char **argv)
   if (optind == argc)
     *operand_lim++ = bad_cast ("-");
 
+  if (O_BINARY)
+    xset_binary_mode (STDIN_FILENO, O_BINARY);
+
   for (char **operandp = argv + optind; operandp < operand_lim; operandp++)
     {
       char *file = *operandp;
--- a/src/mv.c	2016-11-22 12:57:27.000000000 -0600
+++ b/src/mv.c	2017-02-03 13:32:48.756816900 -0600
@@ -93,7 +93,7 @@ rm_option_init (struct rm_options *x)
   x->require_restore_cwd = true;
 
   {
-    static struct dev_ino dev_ino_buf;
+    static struct root_dev_ino dev_ino_buf;
     x->root_dev_ino = get_root_dev_ino (&dev_ino_buf);
     if (x->root_dev_ino == NULL)
       die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
--- a/src/pwd.c	2016-11-06 16:15:30.000000000 -0600
+++ b/src/pwd.c	2017-02-03 13:32:48.756816900 -0600
@@ -268,8 +268,8 @@ static void
 robust_getcwd (struct file_name *file_name)
 {
   size_t height = 1;
-  struct dev_ino dev_ino_buf;
-  struct dev_ino *root_dev_ino = get_root_dev_ino (&dev_ino_buf);
+  struct root_dev_ino dev_ino_buf;
+  struct root_dev_ino *root_dev_ino = get_root_dev_ino (&dev_ino_buf);
   struct stat dot_sb;
 
   if (root_dev_ino == NULL)
@@ -282,7 +282,7 @@ robust_getcwd (struct file_name *file_na
   while (1)
     {
       /* If we've reached the root, we're done.  */
-      if (SAME_INODE (dot_sb, *root_dev_ino))
+      if (ROOT_DEV_INO_CHECK (root_dev_ino, &dot_sb))
         break;
 
       find_dir_entry (&dot_sb, file_name, height++);
@@ -291,6 +291,9 @@ robust_getcwd (struct file_name *file_na
   /* See if a leading slash is needed; file_name_prepend adds one.  */
   if (file_name->start[0] == '\0')
     file_name_prepend (file_name, "", 0);
+  /* If we aren't in `/', we must be in `//'.  */
+  if (! SAME_INODE (root_dev_ino->single_slash, dot_sb))
+    file_name_prepend (file_name, "", 0);
 }
 
 
--- a/src/remove.h	2016-03-09 04:15:39.000000000 -0600
+++ b/src/remove.h	2017-02-03 13:32:48.756816900 -0600
@@ -54,7 +54,7 @@
 
   /* Pointer to the device and inode numbers of '/', when --recursive
      and preserving '/'.  Otherwise NULL.  */
-  struct dev_ino *root_dev_ino;
+  struct root_dev_ino *root_dev_ino;
 
   /* If true, do not traverse into (or remove) any directory that is
      the root of a file system.  I.e., a separate device.  */
--- a/src/rm.c	2016-11-06 16:15:30.000000000 -0600
+++ b/src/rm.c	2017-02-03 13:32:48.756816900 -0600
@@ -342,7 +342,7 @@ main (int argc, char **argv)
 
   if (x.recursive && preserve_root)
     {
-      static struct dev_ino dev_ino_buf;
+      static struct root_dev_ino dev_ino_buf;
       x.root_dev_ino = get_root_dev_ino (&dev_ino_buf);
       if (x.root_dev_ino == NULL)
         die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
--- a/src/stat.c	2016-11-26 18:28:45.000000000 -0600
+++ b/src/stat.c	2017-02-03 13:32:48.756816900 -0600
@@ -74,6 +74,13 @@
 #include "find-mount-point.h"
 #include "xvasprintf.h"
 
+#ifdef __CYGWIN__
+# include "cygwin.h"
+/* Whether .exe should be appended to command-line args as needed.  */
+static bool append_exe;
+# define APPEND_EXE_OPTION 10000
+#endif
+
 #if USE_STATVFS
 # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATVFS_F_FSID_IS_INTEGER
 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE
@@ -201,6 +208,9 @@
   {"printf", required_argument, NULL, PRINTF_OPTION},
   {"terse", no_argument, NULL, 't'},
   {"cached", required_argument, NULL, 0},
+#ifdef __CYGWIN__
+  {"append-exe", no_argument, NULL, APPEND_EXE_OPTION},
+#endif
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -1352,14 +1362,26 @@
       return false;
     }
 
+#ifdef __CYGWIN__
+  char *name_alt = NULL;
+  if (append_exe && 0 < cygwin_spelling (filename))
+    CYGWIN_APPEND_EXE (name_alt, filename);
+#endif /* __CYGWIN__ */
+
   if (STATFS (filename, &statfsbuf) != 0)
     {
       error (0, errno, _("cannot read file system information for %s"),
              quoteaf (filename));
+#if __CYGWIN__
+      freea (name_alt);
+#endif /* __CYGWIN__ */
       return false;
     }
 
   bool fail = print_it (format, -1, filename, print_statfs, &statfsbuf);
+#if __CYGWIN__
+  freea (name_alt);
+#endif /* __CYGWIN__ */
   return ! fail;
 }
 
@@ -1421,6 +1421,7 @@
   struct print_args pa;
   pa.st = &statbuf;
   pa.btime = (struct timespec) {-1, -1};
+  char *name_alt = NULL;
 
   if (0 <= fd)
     {
@@ -1433,18 +1433,28 @@
   /* We can't use the shorter
      (follow_links?stat:lstat) (filename, &statbug)
      since stat might be a function-like macro.  */
-  else if ((follow_links
-            ? stat (filename, &statbuf)
-            : lstat (filename, &statbuf)) != 0)
+  else
     {
-      error (0, errno, _("cannot stat %s"), quoteaf (filename));
-      return false;
+      if ((follow_links
+	   ? stat (filename, &statbuf)
+	   : lstat (filename, &statbuf)) != 0)
+	{
+	  error (0, errno, _("cannot stat %s"), quoteaf (filename));
+	  return false;
+	}
+#ifdef __CYGWIN__
+      if (append_exe && 0 < cygwin_spelling (filename))
+        CYGWIN_APPEND_EXE (name_alt, filename);
+#endif /* __CYGWIN__ */
     }
 
   if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
     format = format2;
 
   bool fail = print_it (format, fd, filename, print_stat, &pa);
+#if __CYGWIN__
+  freea (name_alt);
+#endif /* __CYGWIN__ */
   return ! fail;
 }
 #endif /* USE_STATX */
@@ -1513,6 +1546,11 @@
                           if you want a newline, include \\n in FORMAT\n\
   -t, --terse           print the information in terse form\n\
 "), stdout);
+#if __CYGWIN__
+      fputs (_("\
+      --append-exe      append .exe if cygwin magic was needed\n\
+"), stdout);
+#endif /* __CYGWIN__ */
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
 
@@ -1649,6 +1687,12 @@
           terse = true;
           break;
 
+#if __CYGWIN__
+        case APPEND_EXE_OPTION:
+          append_exe = true;
+          break;
+#endif /* __CYGWIN__ */
+
         case_GETOPT_HELP_CHAR;
 
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
--- a/src/copy.c	2016-11-22 12:57:27.000000000 -0600
+++ b/src/copy.c	2017-02-03 13:32:48.741217700 -0600
@@ -82,6 +82,10 @@
 # include <linux/fs.h>
 #endif
 
+#ifdef __CYGWIN__
+# include "cygwin.h"
+#endif
+
 #if !defined FICLONE && defined __linux__
 # define FICLONE _IOW (0x94, 9, int)
 #endif
@@ -1427,7 +1431,11 @@
 static bool
 same_file_ok (char const *src_name, struct stat const *src_sb,
               char const *dst_name, struct stat const *dst_sb,
-              const struct cp_options *x, bool *return_now)
+              const struct cp_options *x, bool *return_now
+#ifdef __CYGWIN__
+	      , bool *case_change
+#endif
+	      )
 {
   const struct stat *src_sb_link;
   const struct stat *dst_sb_link;
@@ -1571,6 +1579,18 @@
       if (S_ISLNK (dst_sb_link->st_mode))
         return true;
 
+#if __CYGWIN__
+      /* If the files have the same name, but differ in case, then let
+	 rename() change the case.  */
+      if (same_link && x->move_mode && same_name (src_name, dst_name)
+	  && memcmp (last_component (src_name), last_component (dst_name),
+		     base_len (src_name)))
+	{
+	  *case_change = true;
+	  return true;
+	}
+#endif /* __CYGWIN__ */
+
       /* It's not ok if they're distinct hard links to the same file as
          this causes a race condition and we may lose data in this case.  */
       if (same_link
@@ -1930,6 +1950,9 @@
     }
 
   bool dereference = should_dereference (x, command_line_arg);
+#if __CYGWIN__
+	  bool case_change = false;
+#endif /* __CYGWIN__ */
 
   if (!new_dst)
     {
@@ -1974,7 +1997,11 @@
 
           if (x->interactive != I_ALWAYS_NO
               && ! same_file_ok (src_name, &src_sb, dst_name, &dst_sb,
-                                 x, &return_now))
+                                 x, &return_now
+#ifdef __CYGWIN__
+			      , &case_change
+#endif
+			      ))
             {
               error (0, 0, _("%s and %s are the same file"),
                      quoteaf_n (0, src_name), quoteaf_n (1, dst_name));
@@ -2033,6 +2060,9 @@
              cp and mv treat -i and -f differently.  */
           if (x->move_mode)
             {
+#if __CYGWIN__
+	      if (!case_change)
+#endif
               if (abandon_move (x, dst_name, &dst_sb))
                 {
                   /* Pretend the rename succeeded, so the caller (mv)
@@ -2174,7 +2204,11 @@
                    /* Never unlink dst_name when in move mode.  */
                    && ! x->move_mode
                    && (x->unlink_dest_before_opening
-                       || (x->preserve_links && 1 < dst_sb.st_nlink)
+                       || (x->preserve_links && 1 < dst_sb.st_nlink
+#ifdef __CYGWIN__
+			   && !case_change
+#endif
+			   )
                        || (x->dereference == DEREF_NEVER
                            && ! S_ISREG (src_sb.st_mode))
                        ))
@@ -2973,6 +3007,21 @@
 {
   assert (valid_options (options));
 
+#ifdef __CYGWIN__
+  /* .exe magic - if src exists with an implicit .exe suffix and is
+     not a symlink, but dst does not exist and was also specified
+     without a suffix, then append .exe to dst.  */
+  int cygwin = cygwin_spelling (src_name);
+  char *p;
+  if (cygwin == 2
+      && ((p = strchr (dst_name, '\0') - 4) <= dst_name
+          || strcasecmp (p, ".exe") != 0))
+    {
+      cygwin = 3;
+      CYGWIN_APPEND_EXE (p, dst_name);
+    }
+#endif /* __CYGWIN__ */
+
   /* Record the file names: they're used in case of error, when copying
      a directory into itself.  I don't like to make these tools do *any*
      extra work in the common case when that work is solely to handle
@@ -2984,10 +3033,16 @@
   top_level_dst_name = dst_name;
 
   bool first_dir_created_per_command_line_arg = false;
-  return copy_internal (src_name, dst_name, nonexistent_dst, NULL, NULL,
+  bool done;
+  done = copy_internal (src_name, dst_name, nonexistent_dst, NULL, NULL,
                         options, true,
                         &first_dir_created_per_command_line_arg,
                         copy_into_self, rename_succeeded);
+#ifdef __CYGWIN__
+  if (cygwin == 3)
+    freea ((char *) dst_name);
+#endif
+  return done;
 }
 
 /* Set *X to the default options for a value of type struct cp_options.  */
