159 lines
5.5 KiB
Diff
159 lines
5.5 KiB
Diff
--- origsrc/src/copy.c 2023-08-29 05:39:27.000000000 -0600
|
|
+++ src/src/copy.c 2023-09-09 22:06:16.745397400 -0600
|
|
@@ -83,6 +83,10 @@
|
|
#ifdef HAVE_LINUX_FS_H
|
|
# include <linux/fs.h>
|
|
#endif
|
|
+
|
|
+#ifdef __CYGWIN__
|
|
+# include "cygwin.h"
|
|
+#endif
|
|
|
|
#if !defined FICLONE && defined __linux__
|
|
# define FICLONE _IOW (0x94, 9, int)
|
|
@@ -1738,7 +1742,11 @@ close_src_desc:
|
|
static bool
|
|
same_file_ok (char const *src_name, struct stat const *src_sb,
|
|
int dst_dirfd, char const *dst_relname, struct stat const *dst_sb,
|
|
- const struct cp_options *x, bool *return_now)
|
|
+ const struct cp_options *x, bool *return_now
|
|
+#if __CYGWIN__
|
|
+ , bool *case_change
|
|
+#endif
|
|
+ )
|
|
{
|
|
const struct stat *src_sb_link;
|
|
const struct stat *dst_sb_link;
|
|
@@ -1883,6 +1891,18 @@ same_file_ok (char const *src_name, stru
|
|
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_relname)
|
|
+ && memcmp (last_component (src_name), last_component (dst_relname),
|
|
+ base_len (src_name)))
|
|
+ {
|
|
+ *case_change = true;
|
|
+ return true;
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* 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
|
|
@@ -2316,13 +2336,23 @@ copy_internal (char const *src_name, cha
|
|
if (!use_lstat && nonexistent_dst < 0)
|
|
new_dst = true;
|
|
else if (follow_fstatat (dst_dirfd, drelname, &dst_sb, fstatat_flags)
|
|
- == 0)
|
|
+ == 0
|
|
+#if __CYGWIN__
|
|
+ /* stat("a") succeeds if "a.exe" - only identical accepted. */
|
|
+ && cygwin_spelling (drelname) == 0
|
|
+#endif
|
|
+ )
|
|
{
|
|
have_dst_lstat = use_lstat;
|
|
rename_errno = EEXIST;
|
|
}
|
|
else
|
|
{
|
|
+#if __CYGWIN__
|
|
+ /* only DST_RELNAME.exe exists - want non-existant DST_RELNAME. */
|
|
+ if (cygwin_spelling (drelname) != 0)
|
|
+ errno = ENOENT;
|
|
+#endif
|
|
if (errno == ELOOP && x->unlink_dest_after_failed_open)
|
|
/* leave new_dst=false so we unlink later. */;
|
|
else if (errno != ENOENT)
|
|
@@ -2340,10 +2370,17 @@ copy_internal (char const *src_name, cha
|
|
bool return_now = false;
|
|
bool return_val = true;
|
|
bool skipped = false;
|
|
+#if __CYGWIN__
|
|
+ bool case_change = false;
|
|
+#endif
|
|
|
|
if ((x->interactive != I_ALWAYS_NO && x->interactive != I_ALWAYS_SKIP)
|
|
&& ! same_file_ok (src_name, &src_sb, dst_dirfd, drelname,
|
|
- &dst_sb, x, &return_now))
|
|
+ &dst_sb, x, &return_now
|
|
+#if __CYGWIN__
|
|
+ , &case_change
|
|
+#endif
|
|
+ ))
|
|
{
|
|
error (0, 0, _("%s and %s are the same file"),
|
|
quoteaf_n (0, src_name), quoteaf_n (1, dst_name));
|
|
@@ -2406,6 +2443,9 @@ copy_internal (char const *src_name, cha
|
|
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_dirfd, drelname, &dst_sb))
|
|
{
|
|
/* Pretend the rename succeeded, so the caller (mv)
|
|
@@ -2572,7 +2612,11 @@ skip:
|
|
&& ! x->move_mode
|
|
&& (x->unlink_dest_before_opening
|
|
|| (x->data_copy_required
|
|
- && ((x->preserve_links && 1 < dst_sb.st_nlink)
|
|
+ && ((x->preserve_links && 1 < dst_sb.st_nlink
|
|
+#if __CYGWIN__
|
|
+ && ! case_change
|
|
+#endif
|
|
+ )
|
|
|| (x->dereference == DEREF_NEVER
|
|
&& ! S_ISREG (src_sb.st_mode))))
|
|
))
|
|
@@ -3407,6 +3451,24 @@ copy (char const *src_name, char const *
|
|
{
|
|
valid_options (options);
|
|
|
|
+#if __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);
|
|
+ if ((p = strchr (dst_relname, '\0') - 4) <= dst_relname
|
|
+ || strcasecmp (p, ".exe") != 0)
|
|
+ CYGWIN_APPEND_EXE (p, dst_relname);
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* 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
|
|
@@ -3418,11 +3480,19 @@ copy (char const *src_name, char const *
|
|
top_level_dst_name = dst_name;
|
|
|
|
bool first_dir_created_per_command_line_arg = false;
|
|
- return copy_internal (src_name, dst_name, dst_dirfd, dst_relname,
|
|
+ bool done = copy_internal (src_name, dst_name, dst_dirfd, dst_relname,
|
|
nonexistent_dst, nullptr, nullptr,
|
|
options, true,
|
|
&first_dir_created_per_command_line_arg,
|
|
copy_into_self, rename_succeeded);
|
|
+#if __CYGWIN__
|
|
+ if (cygwin == 3)
|
|
+ {
|
|
+ freea ((char *) dst_name);
|
|
+ freea ((char *) dst_relname);
|
|
+ }
|
|
+#endif
|
|
+ return done;
|
|
}
|
|
|
|
/* Set *X to the default options for a value of type struct cp_options. */
|