@@ -1571,6 +1571,86 @@ conv_path_list (const char *src, char *dst, size_t size,
1571
1571
1572
1572
/* ********************* Symbolic Link Support **************************/
1573
1573
1574
+ /*
1575
+ Create a deep copy of src as dst, while avoiding descending in origpath.
1576
+ */
1577
+ static int
1578
+ recursiveCopy (char * src, char * dst, const char * origpath)
1579
+ {
1580
+ WIN32_FIND_DATA dHfile;
1581
+ HANDLE dH;
1582
+ BOOL findfiles;
1583
+ int srcpos = strlen (src);
1584
+ int dstpos = strlen (dst);
1585
+ int res = -1 ;
1586
+
1587
+ debug_printf (" recursiveCopy (%s, %s)" , src, dst);
1588
+
1589
+ /* Create the destination directory */
1590
+ if (!CreateDirectoryEx (src, dst, NULL ))
1591
+ {
1592
+ debug_printf (" CreateDirectoryEx(%s, %s, 0) failed" , src, dst);
1593
+ __seterrno ();
1594
+ goto done;
1595
+ }
1596
+ /* Descend into the source directory */
1597
+ if (srcpos + 2 >= MAX_PATH || dstpos + 1 >= MAX_PATH)
1598
+ {
1599
+ set_errno (ENAMETOOLONG);
1600
+ goto done;
1601
+ }
1602
+ strcat (src, " \\ *" );
1603
+ strcat (dst, " \\ " );
1604
+ dH = FindFirstFile (src, &dHfile);
1605
+ debug_printf (" dHfile(1): %s" , dHfile.cFileName );
1606
+ findfiles = FindNextFile (dH, &dHfile);
1607
+ debug_printf (" dHfile(2): %s" , dHfile.cFileName );
1608
+ findfiles = FindNextFile (dH, &dHfile);
1609
+ while (findfiles)
1610
+ {
1611
+ /* Append the directory item filename to both source and destination */
1612
+ int filelen = strlen (dHfile.cFileName );
1613
+ debug_printf (" dHfile(3): %s" , dHfile.cFileName );
1614
+ if (srcpos + 1 + filelen >= MAX_PATH ||
1615
+ dstpos + 1 + filelen >= MAX_PATH)
1616
+ {
1617
+ set_errno (ENAMETOOLONG);
1618
+ goto done;
1619
+ }
1620
+ strcpy (&src[srcpos+1 ], dHfile.cFileName );
1621
+ strcpy (&dst[dstpos+1 ], dHfile.cFileName );
1622
+ debug_printf (" %s -> %s" , src, dst);
1623
+ if (dHfile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1624
+ {
1625
+ /* Recurse into the child directory */
1626
+ debug_printf (" %s <-> %s" , src, origpath);
1627
+ if (strcmp (src, origpath)) // avoids endless recursion
1628
+ if (recursiveCopy (src, dst, origpath))
1629
+ goto done;
1630
+ }
1631
+ else
1632
+ {
1633
+ /* Just copy the file */
1634
+ if (!CopyFile (src, dst, FALSE ))
1635
+ {
1636
+ __seterrno ();
1637
+ goto done;
1638
+ }
1639
+ }
1640
+ findfiles = FindNextFile (dH, &dHfile);
1641
+ }
1642
+ if (GetLastError () != ERROR_NO_MORE_FILES)
1643
+ {
1644
+ __seterrno ();
1645
+ goto done;
1646
+ }
1647
+ res = 0 ;
1648
+
1649
+ done:
1650
+
1651
+ return res;
1652
+ }
1653
+
1574
1654
/* Create a symlink from FROMPATH to TOPATH. */
1575
1655
1576
1656
extern " C" int
@@ -1995,6 +2075,73 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
1995
2075
}
1996
2076
else
1997
2077
{
2078
+ path_conv src_path;
2079
+ src_path.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
2080
+ if (src_path.error )
2081
+ {
2082
+ set_errno (src_path.error );
2083
+ __leave;
2084
+ }
2085
+ if (!src_path.isdevice () && !src_path.is_fs_special ())
2086
+ {
2087
+ /* MSYS copy file instead make symlink */
2088
+
2089
+ char * real_oldpath;
2090
+ if (isabspath (oldpath))
2091
+ strcpy (real_oldpath = tp.c_get (), oldpath);
2092
+ else
2093
+ /* Find the real source path, relative
2094
+ to the directory of the destination */
2095
+ {
2096
+ /* Determine the character position of the last path component */
2097
+ int pos = strlen (newpath);
2098
+ while (--pos >= 0 )
2099
+ if (isdirsep (newpath[pos]))
2100
+ break ;
2101
+ /* Append the source path to the directory
2102
+ component of the destination */
2103
+ if (pos+1 +strlen (oldpath) >= MAX_PATH)
2104
+ {
2105
+ set_errno (ENAMETOOLONG);
2106
+ __leave;
2107
+ }
2108
+ strcpy (real_oldpath = tp.c_get (), newpath);
2109
+ strcpy (&real_oldpath[pos+1 ], oldpath);
2110
+ }
2111
+
2112
+ /* As a MSYS limitation, the source path must exist. */
2113
+ path_conv win32_oldpath;
2114
+ win32_oldpath.check (real_oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
2115
+ if (!win32_oldpath.exists ())
2116
+ {
2117
+ set_errno (ENOENT);
2118
+ __leave;
2119
+ }
2120
+
2121
+ char *w_newpath;
2122
+ char *w_oldpath;
2123
+ stpcpy (w_newpath = tp.c_get (), win32_newpath.get_win32 ());
2124
+ stpcpy (w_oldpath = tp.c_get (), win32_oldpath.get_win32 ());
2125
+ if (win32_oldpath.isdir ())
2126
+ {
2127
+ char *origpath;
2128
+ strcpy (origpath = tp.c_get (), w_oldpath);
2129
+ res = recursiveCopy (w_oldpath, w_newpath, origpath);
2130
+ }
2131
+ else
2132
+ {
2133
+ if (!CopyFile (w_oldpath, w_newpath, FALSE ))
2134
+ {
2135
+ __seterrno ();
2136
+ }
2137
+ else
2138
+ {
2139
+ res = 0 ;
2140
+ }
2141
+ }
2142
+ __leave;
2143
+ }
2144
+
1998
2145
/* Default technique creating a symlink. */
1999
2146
buf = tp.t_get ();
2000
2147
cp = stpcpy (buf, SYMLINK_COOKIE);
0 commit comments