@@ -2156,6 +2156,77 @@ symlink_wsl (const char *oldpath, path_conv &win32_newpath)
2156
2156
return 0 ;
2157
2157
}
2158
2158
2159
+ int
2160
+ symlink_deepcopy (const char *oldpath, path_conv &win32_newpath)
2161
+ {
2162
+ path_conv win32_oldpath;
2163
+ /* The symlink target is relative to the directory in which the
2164
+ symlink gets created, not relative to the cwd. Therefore we
2165
+ have to mangle the path quite a bit before calling path_conv.*/
2166
+ mangle_symlink_target (oldpath, win32_newpath, win32_oldpath);
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 ,
2216
+ NULL , NULL , NULL ,
2217
+ COPY_FILE_COPY_SYMLINK|
2218
+ (isdirlink ? COPY_FILE_DIRECTORY : 0 )))
2219
+ {
2220
+ __seterrno ();
2221
+ return -1 ;
2222
+ }
2223
+ else
2224
+ {
2225
+ return 0 ;
2226
+ }
2227
+ }
2228
+ }
2229
+
2159
2230
int
2160
2231
symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2161
2232
{
@@ -2223,6 +2294,13 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2223
2294
case WSYM_nfs:
2224
2295
res = symlink_nfs (oldpath, win32_newpath);
2225
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;
2226
2304
case WSYM_native:
2227
2305
case WSYM_nativestrict:
2228
2306
res = symlink_native (oldpath, win32_newpath);
@@ -2239,6 +2317,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2239
2317
wsym_type = WSYM_default;
2240
2318
fallthrough;
2241
2319
case WSYM_default:
2320
+ handle_default:
2242
2321
if (win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)
2243
2322
{
2244
2323
res = symlink_wsl (oldpath, win32_newpath);
@@ -2375,79 +2454,8 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
2375
2454
* sizeof (WCHAR);
2376
2455
cp += *plen;
2377
2456
}
2378
- else
2457
+ else /* wsym_type == WSYM_sysfile */
2379
2458
{
2380
- if (wsym_type == WSYM_deepcopy)
2381
- {
2382
- path_conv win32_oldpath;
2383
- /* The symlink target is relative to the directory in which the
2384
- symlink gets created, not relative to the cwd. Therefore we
2385
- have to mangle the path quite a bit before calling path_conv.*/
2386
- mangle_symlink_target (oldpath, win32_newpath, win32_oldpath);
2387
- if (win32_oldpath.error )
2388
- {
2389
- set_errno (win32_oldpath.error );
2390
- __leave;
2391
- }
2392
- if (!win32_oldpath.isspecial ())
2393
- {
2394
- /* MSYS copy file instead make symlink */
2395
- /* As a MSYS limitation, the source path must exist. */
2396
- if (!win32_oldpath.exists ())
2397
- {
2398
- set_errno (ENOENT);
2399
- __leave;
2400
- }
2401
-
2402
- PUNICODE_STRING w_oldpath = win32_oldpath.get_nt_native_path ();
2403
- PUNICODE_STRING w_newpath = win32_newpath.get_nt_native_path ();
2404
- if (w_oldpath->Buffer [1 ] == L' ?' )
2405
- w_oldpath->Buffer [1 ] = L' \\ ' ;
2406
- if (w_newpath->Buffer [1 ] == L' ?' )
2407
- w_newpath->Buffer [1 ] = L' \\ ' ;
2408
- if (win32_oldpath.isdir ())
2409
- {
2410
- /* we need a larger UNICODE_STRING MaximumLength than
2411
- get_nt_native_path allocates for the recursive copy */
2412
- UNICODE_STRING u_oldpath, u_newpath;
2413
- RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2414
- RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2415
- res = recursiveCopy (&u_oldpath, &u_newpath,
2416
- u_oldpath.Length , u_newpath.Length );
2417
- }
2418
- else
2419
- {
2420
- bool isdirlink = false ;
2421
- if (win32_oldpath.issymlink () &&
2422
- win32_oldpath.is_known_reparse_point ())
2423
- {
2424
- /* Is there a better way to know this? */
2425
- DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2426
- !!win32_oldpath.objcaseinsensitive ());
2427
- if (attr == INVALID_FILE_ATTRIBUTES)
2428
- {
2429
- __seterrno ();
2430
- __leave;
2431
- }
2432
- isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2433
- }
2434
- if (!CopyFileExW (w_oldpath->Buffer , w_newpath->Buffer ,
2435
- NULL , NULL , NULL ,
2436
- COPY_FILE_COPY_SYMLINK|
2437
- (isdirlink ? COPY_FILE_DIRECTORY : 0 )))
2438
- {
2439
- __seterrno ();
2440
- }
2441
- else
2442
- {
2443
- res = 0 ;
2444
- }
2445
- }
2446
- __leave;
2447
- }
2448
- }
2449
-
2450
- /* wsym_type == WSYM_sysfile */
2451
2459
/* Default technique creating a symlink. */
2452
2460
buf = tp.t_get ();
2453
2461
cp = stpcpy (buf, SYMLINK_COOKIE);
0 commit comments