aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-05-13 08:14:42 +0100
committerRon Yorston <rmy@pobox.com>2022-05-14 10:39:33 +0100
commitb0696b94ab963fe0dd47f5c1ed6327a4337afa09 (patch)
tree4929d2987b6c0c183d5ebfdb8960bf475068e8f2 /win32
parent5388501a08affedec5c97218c7461a9f21566007 (diff)
downloadbusybox-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.c19
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
1380ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) 1382ssize_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();