diff options
author | Ron Yorston <rmy@pobox.com> | 2022-05-13 08:14:42 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-05-14 10:39:33 +0100 |
commit | b0696b94ab963fe0dd47f5c1ed6327a4337afa09 (patch) | |
tree | 4929d2987b6c0c183d5ebfdb8960bf475068e8f2 /win32 | |
parent | 5388501a08affedec5c97218c7461a9f21566007 (diff) | |
download | busybox-w32-b0696b94ab963fe0dd47f5c1ed6327a4337afa09.tar.gz busybox-w32-b0696b94ab963fe0dd47f5c1ed6327a4337afa09.tar.bz2 busybox-w32-b0696b94ab963fe0dd47f5c1ed6327a4337afa09.zip |
win32: treat junctions as symlinks
Directory junctions were always followed to their target so they
appeared to *be* directories. This resulted in counter-intuitive
behaviour:
- a directory junction could be removed with rmdir even though
the directory wasn't empty;
- 'rm -rf' on a directory junction deleted it but also deleted
the contents of the linked directory.
A better approximation is to treat directory junctions as
symbolic links.
(GitHub issue #254)
Diffstat (limited to 'win32')
-rw-r--r-- | win32/mingw.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index 6954ee9b5..539aa48d2 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -571,7 +571,8 @@ static int get_symlink_data(DWORD attr, const char *pathname, | |||
571 | if (handle != INVALID_HANDLE_VALUE) { | 571 | if (handle != INVALID_HANDLE_VALUE) { |
572 | FindClose(handle); | 572 | FindClose(handle); |
573 | return ((fbuf->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && | 573 | return ((fbuf->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && |
574 | fbuf->dwReserved0 == IO_REPARSE_TAG_SYMLINK); | 574 | (fbuf->dwReserved0 == IO_REPARSE_TAG_SYMLINK || |
575 | fbuf->dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)); | ||
575 | } | 576 | } |
576 | } | 577 | } |
577 | return 0; | 578 | return 0; |
@@ -1377,6 +1378,7 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf) | |||
1377 | } | 1378 | } |
1378 | 1379 | ||
1379 | #define SRPB rptr->SymbolicLinkReparseBuffer | 1380 | #define SRPB rptr->SymbolicLinkReparseBuffer |
1381 | #define MRPB rptr->MountPointReparseBuffer | ||
1380 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | 1382 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) |
1381 | { | 1383 | { |
1382 | HANDLE h; | 1384 | HANDLE h; |
@@ -1388,24 +1390,29 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | |||
1388 | BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; | 1390 | BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; |
1389 | PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf; | 1391 | PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf; |
1390 | BOOL status; | 1392 | BOOL status; |
1393 | size_t len; | ||
1394 | WCHAR *name = NULL; | ||
1391 | 1395 | ||
1392 | status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, | 1396 | status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, |
1393 | rptr, sizeof(rbuf), &nbytes, NULL); | 1397 | rptr, sizeof(rbuf), &nbytes, NULL); |
1394 | CloseHandle(h); | 1398 | CloseHandle(h); |
1395 | 1399 | ||
1396 | if (status && rptr->ReparseTag == IO_REPARSE_TAG_SYMLINK) { | 1400 | if (status && rptr->ReparseTag == IO_REPARSE_TAG_SYMLINK) { |
1397 | size_t len = SRPB.SubstituteNameLength/sizeof(WCHAR); | 1401 | len = SRPB.SubstituteNameLength/sizeof(WCHAR); |
1398 | WCHAR *name = SRPB.PathBuffer + | 1402 | name = SRPB.PathBuffer + SRPB.SubstituteNameOffset/sizeof(WCHAR); |
1399 | SRPB.SubstituteNameOffset/sizeof(WCHAR); | 1403 | } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { |
1404 | len = MRPB.SubstituteNameLength/sizeof(WCHAR); | ||
1405 | name = MRPB.PathBuffer + MRPB.SubstituteNameOffset/sizeof(WCHAR); | ||
1406 | } | ||
1400 | 1407 | ||
1408 | if (name) { | ||
1401 | name[len] = 0; | 1409 | name[len] = 0; |
1402 | name = normalize_ntpath(name); | 1410 | name = normalize_ntpath(name); |
1403 | len = wcslen(name); | 1411 | len = wcslen(name); |
1404 | if (len > bufsiz) | 1412 | if (len > bufsiz) |
1405 | len = bufsiz; | 1413 | len = bufsiz; |
1406 | if (WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0)) { | 1414 | if (WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0)) |
1407 | return len; | 1415 | return len; |
1408 | } | ||
1409 | } | 1416 | } |
1410 | } | 1417 | } |
1411 | errno = err_win_to_posix(); | 1418 | errno = err_win_to_posix(); |