@@ -2144,6 +2144,88 @@ symlink_wsl (const char *oldpath, path_conv &win32_newpath)
2144
2144
return 0 ;
2145
2145
}
2146
2146
2147
+ int
2148
+ symlink_deepcopy (const char *oldpath, path_conv &win32_newpath)
2149
+ {
2150
+ tmp_pathbuf tp;
2151
+ path_conv win32_oldpath;
2152
+
2153
+ /* The symlink target is relative to the directory in which the
2154
+ symlink gets created, not relative to the cwd. Therefore we
2155
+ have to mangle the path quite a bit before calling path_conv.*/
2156
+ if (isabspath (oldpath))
2157
+ win32_oldpath.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
2158
+ else
2159
+ {
2160
+ size_t len = strrchr (win32_newpath.get_posix (), ' /' )
2161
+ - win32_newpath.get_posix () + 1 ;
2162
+ char *absoldpath = tp.t_get ();
2163
+ stpcpy (stpncpy (absoldpath, win32_newpath.get_posix (), len),
2164
+ oldpath);
2165
+ win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes);
2166
+ }
2167
+ if (win32_oldpath.error )
2168
+ {
2169
+ set_errno (win32_oldpath.error );
2170
+ return -1 ;
2171
+ }
2172
+ if (win32_oldpath.isspecial ())
2173
+ return -2 ;
2174
+
2175
+ /* MSYS copy file instead make symlink */
2176
+ /* As a MSYS limitation, the source path must exist. */
2177
+ if (!win32_oldpath.exists ())
2178
+ {
2179
+ set_errno (ENOENT);
2180
+ return -1 ;
2181
+ }
2182
+
2183
+ PUNICODE_STRING w_oldpath = win32_oldpath.get_nt_native_path ();
2184
+ PUNICODE_STRING w_newpath = win32_newpath.get_nt_native_path ();
2185
+ if (w_oldpath->Buffer [1 ] == L' ?' )
2186
+ w_oldpath->Buffer [1 ] = L' \\ ' ;
2187
+ if (w_newpath->Buffer [1 ] == L' ?' )
2188
+ w_newpath->Buffer [1 ] = L' \\ ' ;
2189
+ if (win32_oldpath.isdir ())
2190
+ {
2191
+ /* we need a larger UNICODE_STRING MaximumLength than
2192
+ get_nt_native_path allocates for the recursive copy */
2193
+ UNICODE_STRING u_oldpath, u_newpath;
2194
+ RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2195
+ RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2196
+ return recursiveCopy (&u_oldpath, &u_newpath,
2197
+ u_oldpath.Length , u_newpath.Length );
2198
+ }
2199
+ else
2200
+ {
2201
+ bool isdirlink = false ;
2202
+ if (win32_oldpath.issymlink () &&
2203
+ win32_oldpath.is_known_reparse_point ())
2204
+ {
2205
+ /* Is there a better way to know this? */
2206
+ DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2207
+ !!win32_oldpath.objcaseinsensitive ());
2208
+ if (attr == INVALID_FILE_ATTRIBUTES)
2209
+ {
2210
+ __seterrno ();
2211
+ return -1 ;
2212
+ }
2213
+ isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2214
+ }
2215
+ if (!CopyFileExW (w_oldpath->Buffer , w_newpath->Buffer , NULL , NULL , NULL ,
2216
+ COPY_FILE_COPY_SYMLINK|
2217
+ (isdirlink ? COPY_FILE_DIRECTORY : 0 )))
2218
+ {
2219
+ __seterrno ();
2220
+ return -1 ;
2221
+ }
2222
+ else
2223
+ {
2224
+ return 0 ;
2225
+ }
2226
+ }
2227
+ }
2228
+
2147
2229
int
2148
2230
symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2149
2231
{
@@ -2212,6 +2294,13 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2212
2294
case WSYM_nfs:
2213
2295
res = symlink_nfs (oldpath, win32_newpath);
2214
2296
__leave;
2297
+ case WSYM_deepcopy:
2298
+ res = symlink_deepcopy (oldpath, win32_newpath);
2299
+ if (!res || res == -1 )
2300
+ __leave;
2301
+ /* fall back to default symlink type */
2302
+ wsym_type = WSYM_default;
2303
+ goto handle_default;
2215
2304
case WSYM_native:
2216
2305
case WSYM_nativestrict:
2217
2306
res = symlink_native (oldpath, win32_newpath);
@@ -2228,6 +2317,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2228
2317
wsym_type = WSYM_default;
2229
2318
fallthrough;
2230
2319
case WSYM_default:
2320
+ handle_default:
2231
2321
if (win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)
2232
2322
{
2233
2323
res = symlink_wsl (oldpath, win32_newpath);
@@ -2380,90 +2470,6 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2380
2470
}
2381
2471
else /* wsym_type == WSYM_sysfile */
2382
2472
{
2383
- if (wsym_type == WSYM_deepcopy)
2384
- {
2385
- path_conv win32_oldpath;
2386
- /* The symlink target is relative to the directory in which the
2387
- symlink gets created, not relative to the cwd. Therefore we
2388
- have to mangle the path quite a bit before calling path_conv.*/
2389
- if (isabspath (oldpath))
2390
- win32_oldpath.check (oldpath,
2391
- PC_SYM_NOFOLLOW,
2392
- stat_suffixes);
2393
- else
2394
- {
2395
- len = strrchr (win32_newpath.get_posix (), ' /' )
2396
- - win32_newpath.get_posix () + 1 ;
2397
- char *absoldpath = tp.t_get ();
2398
- stpcpy (stpncpy (absoldpath, win32_newpath.get_posix (),
2399
- len),
2400
- oldpath);
2401
- win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW,
2402
- stat_suffixes);
2403
- }
2404
- if (win32_oldpath.error )
2405
- {
2406
- set_errno (win32_oldpath.error );
2407
- __leave;
2408
- }
2409
- if (!win32_oldpath.isspecial ())
2410
- {
2411
- /* MSYS copy file instead make symlink */
2412
- /* As a MSYS limitation, the source path must exist. */
2413
- if (!win32_oldpath.exists ())
2414
- {
2415
- set_errno (ENOENT);
2416
- __leave;
2417
- }
2418
-
2419
- PUNICODE_STRING w_oldpath = win32_oldpath.get_nt_native_path ();
2420
- PUNICODE_STRING w_newpath = win32_newpath.get_nt_native_path ();
2421
- if (w_oldpath->Buffer [1 ] == L' ?' )
2422
- w_oldpath->Buffer [1 ] = L' \\ ' ;
2423
- if (w_newpath->Buffer [1 ] == L' ?' )
2424
- w_newpath->Buffer [1 ] = L' \\ ' ;
2425
- if (win32_oldpath.isdir ())
2426
- {
2427
- /* we need a larger UNICODE_STRING MaximumLength than
2428
- get_nt_native_path allocates for the recursive copy */
2429
- UNICODE_STRING u_oldpath, u_newpath;
2430
- RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2431
- RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2432
- res = recursiveCopy (&u_oldpath, &u_newpath,
2433
- u_oldpath.Length , u_newpath.Length );
2434
- }
2435
- else
2436
- {
2437
- bool isdirlink = false ;
2438
- if (win32_oldpath.issymlink () &&
2439
- win32_oldpath.is_known_reparse_point ())
2440
- {
2441
- /* Is there a better way to know this? */
2442
- DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2443
- !!win32_oldpath.objcaseinsensitive ());
2444
- if (attr == INVALID_FILE_ATTRIBUTES)
2445
- {
2446
- __seterrno ();
2447
- __leave;
2448
- }
2449
- isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2450
- }
2451
- if (!CopyFileExW (w_oldpath->Buffer , w_newpath->Buffer ,
2452
- NULL , NULL , NULL ,
2453
- COPY_FILE_COPY_SYMLINK|
2454
- (isdirlink ? COPY_FILE_DIRECTORY : 0 )))
2455
- {
2456
- __seterrno ();
2457
- }
2458
- else
2459
- {
2460
- res = 0 ;
2461
- }
2462
- }
2463
- __leave;
2464
- }
2465
- }
2466
-
2467
2473
/* Default technique creating a symlink. */
2468
2474
buf = tp.t_get ();
2469
2475
cp = stpcpy (buf, SYMLINK_COOKIE);
0 commit comments