@@ -1643,6 +1643,86 @@ conv_path_list (const char *src, char *dst, size_t size,
1643
1643
1644
1644
/* ********************* Symbolic Link Support **************************/
1645
1645
1646
+ /*
1647
+ Create a deep copy of src as dst, while avoiding descending in origpath.
1648
+ */
1649
+ static int
1650
+ recursiveCopy (char * src, char * dst, const char * origpath)
1651
+ {
1652
+ WIN32_FIND_DATA dHfile;
1653
+ HANDLE dH;
1654
+ BOOL findfiles;
1655
+ int srcpos = strlen (src);
1656
+ int dstpos = strlen (dst);
1657
+ int res = -1 ;
1658
+
1659
+ debug_printf (" recursiveCopy (%s, %s)" , src, dst);
1660
+
1661
+ /* Create the destination directory */
1662
+ if (!CreateDirectoryEx (src, dst, NULL ))
1663
+ {
1664
+ debug_printf (" CreateDirectoryEx(%s, %s, 0) failed" , src, dst);
1665
+ __seterrno ();
1666
+ goto done;
1667
+ }
1668
+ /* Descend into the source directory */
1669
+ if (srcpos + 2 >= MAX_PATH || dstpos + 1 >= MAX_PATH)
1670
+ {
1671
+ set_errno (ENAMETOOLONG);
1672
+ goto done;
1673
+ }
1674
+ strcat (src, " \\ *" );
1675
+ strcat (dst, " \\ " );
1676
+ dH = FindFirstFile (src, &dHfile);
1677
+ debug_printf (" dHfile(1): %s" , dHfile.cFileName );
1678
+ findfiles = FindNextFile (dH, &dHfile);
1679
+ debug_printf (" dHfile(2): %s" , dHfile.cFileName );
1680
+ findfiles = FindNextFile (dH, &dHfile);
1681
+ while (findfiles)
1682
+ {
1683
+ /* Append the directory item filename to both source and destination */
1684
+ int filelen = strlen (dHfile.cFileName );
1685
+ debug_printf (" dHfile(3): %s" , dHfile.cFileName );
1686
+ if (srcpos + 1 + filelen >= MAX_PATH ||
1687
+ dstpos + 1 + filelen >= MAX_PATH)
1688
+ {
1689
+ set_errno (ENAMETOOLONG);
1690
+ goto done;
1691
+ }
1692
+ strcpy (&src[srcpos+1 ], dHfile.cFileName );
1693
+ strcpy (&dst[dstpos+1 ], dHfile.cFileName );
1694
+ debug_printf (" %s -> %s" , src, dst);
1695
+ if (dHfile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1696
+ {
1697
+ /* Recurse into the child directory */
1698
+ debug_printf (" %s <-> %s" , src, origpath);
1699
+ if (strcmp (src, origpath)) // avoids endless recursion
1700
+ if (recursiveCopy (src, dst, origpath))
1701
+ goto done;
1702
+ }
1703
+ else
1704
+ {
1705
+ /* Just copy the file */
1706
+ if (!CopyFile (src, dst, FALSE ))
1707
+ {
1708
+ __seterrno ();
1709
+ goto done;
1710
+ }
1711
+ }
1712
+ findfiles = FindNextFile (dH, &dHfile);
1713
+ }
1714
+ if (GetLastError () != ERROR_NO_MORE_FILES)
1715
+ {
1716
+ __seterrno ();
1717
+ goto done;
1718
+ }
1719
+ res = 0 ;
1720
+
1721
+ done:
1722
+
1723
+ return res;
1724
+ }
1725
+
1646
1726
/* Create a symlink from FROMPATH to TOPATH. */
1647
1727
1648
1728
extern " C" int
@@ -2175,6 +2255,73 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2175
2255
}
2176
2256
else
2177
2257
{
2258
+ path_conv src_path;
2259
+ src_path.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
2260
+ if (src_path.error )
2261
+ {
2262
+ set_errno (src_path.error );
2263
+ __leave;
2264
+ }
2265
+ if (!src_path.isdevice () && !src_path.is_fs_special ())
2266
+ {
2267
+ /* MSYS copy file instead make symlink */
2268
+
2269
+ char * real_oldpath;
2270
+ if (isabspath (oldpath))
2271
+ strcpy (real_oldpath = tp.c_get (), oldpath);
2272
+ else
2273
+ /* Find the real source path, relative
2274
+ to the directory of the destination */
2275
+ {
2276
+ /* Determine the character position of the last path component */
2277
+ int pos = strlen (newpath);
2278
+ while (--pos >= 0 )
2279
+ if (isdirsep (newpath[pos]))
2280
+ break ;
2281
+ /* Append the source path to the directory
2282
+ component of the destination */
2283
+ if (pos+1 +strlen (oldpath) >= MAX_PATH)
2284
+ {
2285
+ set_errno (ENAMETOOLONG);
2286
+ __leave;
2287
+ }
2288
+ strcpy (real_oldpath = tp.c_get (), newpath);
2289
+ strcpy (&real_oldpath[pos+1 ], oldpath);
2290
+ }
2291
+
2292
+ /* As a MSYS limitation, the source path must exist. */
2293
+ path_conv win32_oldpath;
2294
+ win32_oldpath.check (real_oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
2295
+ if (!win32_oldpath.exists ())
2296
+ {
2297
+ set_errno (ENOENT);
2298
+ __leave;
2299
+ }
2300
+
2301
+ char *w_newpath;
2302
+ char *w_oldpath;
2303
+ stpcpy (w_newpath = tp.c_get (), win32_newpath.get_win32 ());
2304
+ stpcpy (w_oldpath = tp.c_get (), win32_oldpath.get_win32 ());
2305
+ if (win32_oldpath.isdir ())
2306
+ {
2307
+ char *origpath;
2308
+ strcpy (origpath = tp.c_get (), w_oldpath);
2309
+ res = recursiveCopy (w_oldpath, w_newpath, origpath);
2310
+ }
2311
+ else
2312
+ {
2313
+ if (!CopyFile (w_oldpath, w_newpath, FALSE ))
2314
+ {
2315
+ __seterrno ();
2316
+ }
2317
+ else
2318
+ {
2319
+ res = 0 ;
2320
+ }
2321
+ }
2322
+ __leave;
2323
+ }
2324
+
2178
2325
/* Default technique creating a symlink. */
2179
2326
buf = tp.t_get ();
2180
2327
cp = stpcpy (buf, SYMLINK_COOKIE);
0 commit comments