-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows: make Sys.remove and Unix.unlink delete symlinks to directories #10642
Changes from all commits
78e5996
d9cfda1
2d91196
c5f4866
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/**************************************************************************/ | ||
/* */ | ||
/* OCaml */ | ||
/* */ | ||
/* David Allsopp, MetaStack Solutions Ltd. */ | ||
/* */ | ||
/* Copyright 2015 MetaStack Solutions Ltd. */ | ||
/* */ | ||
/* All rights reserved. This file is distributed under the terms of */ | ||
/* the GNU Lesser General Public License version 2.1, with the */ | ||
/* special exception on linking described in the file LICENSE. */ | ||
/* */ | ||
/**************************************************************************/ | ||
|
||
/* Operating system - Windows specific stuff */ | ||
|
||
#ifndef CAML_WINSUPPORT_H | ||
#define CAML_WINSUPPORT_H | ||
|
||
#if defined(_WIN32) && defined(CAML_INTERNALS) | ||
|
||
#include <windef.h> | ||
|
||
/* | ||
* This structure is defined inconsistently. mingw64 has it in ntdef.h (which | ||
* doesn't look like a primary header) and technically it's part of ntifs.h in | ||
* the WDK. Requiring the WDK is a bit extreme, so the definition is taken from | ||
* ntdef.h. Both ntdef.h and ntifs.h define REPARSE_DATA_BUFFER_HEADER_SIZE | ||
*/ | ||
#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE | ||
typedef struct _REPARSE_DATA_BUFFER | ||
{ | ||
ULONG ReparseTag; | ||
USHORT ReparseDataLength; | ||
USHORT Reserved; | ||
union | ||
{ | ||
struct | ||
{ | ||
USHORT SubstituteNameOffset; | ||
USHORT SubstituteNameLength; | ||
USHORT PrintNameOffset; | ||
USHORT PrintNameLength; | ||
ULONG Flags; | ||
WCHAR PathBuffer[1]; | ||
} SymbolicLinkReparseBuffer; | ||
struct | ||
{ | ||
USHORT SubstituteNameOffset; | ||
USHORT SubstituteNameLength; | ||
USHORT PrintNameOffset; | ||
USHORT PrintNameLength; | ||
WCHAR PathBuffer[1]; | ||
} MountPointReparseBuffer; | ||
struct | ||
{ | ||
UCHAR DataBuffer[1]; | ||
} GenericReparseBuffer; | ||
}; | ||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; | ||
#endif | ||
|
||
#endif | ||
|
||
#endif /* CAML_WINSUPPORT_H */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,8 @@ | |
#include <wtypes.h> | ||
#include <winbase.h> | ||
#include <winsock2.h> | ||
#include <winioctl.h> | ||
#include <direct.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <stdarg.h> | ||
|
@@ -46,6 +48,7 @@ | |
#include "caml/osdeps.h" | ||
#include "caml/signals.h" | ||
#include "caml/sys.h" | ||
#include "caml/winsupport.h" | ||
|
||
#include "caml/config.h" | ||
|
||
|
@@ -797,6 +800,48 @@ int caml_win32_rename(const wchar_t * oldpath, const wchar_t * newpath) | |
return -1; | ||
} | ||
|
||
int caml_win32_unlink(const wchar_t * path) { | ||
int ret; | ||
|
||
ret = _wunlink(path); | ||
/* On Windows, trying to unlink a symlink to a directory will return | ||
* EACCES, but the symlink can be deleted with rmdir. */ | ||
Comment on lines
+807
to
+808
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds like a bug in Windows, but who am I to say. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is certainly amusing that MSDN claims "Microsoft has implemented its symbolic links to function just like UNIX links."! It's a consequence of Windows having two symbolic link types. IIRC you get |
||
if (ret == -1 && errno == EACCES) { | ||
HANDLE h; | ||
DWORD attrs, dummy; | ||
union { | ||
char raw[16384]; | ||
REPARSE_DATA_BUFFER point; | ||
} buffer; | ||
|
||
attrs = GetFileAttributes(path); | ||
if (attrs == INVALID_FILE_ATTRIBUTES || | ||
!(attrs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))) | ||
return -1; | ||
|
||
h = CreateFile(path, | ||
FILE_READ_ATTRIBUTES, | ||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
NULL, | ||
OPEN_EXISTING, | ||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, | ||
NULL); | ||
if (h == INVALID_HANDLE_VALUE) | ||
return -1; | ||
|
||
ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, &buffer.point, | ||
sizeof(buffer.raw), &dummy, NULL); | ||
CloseHandle(h); | ||
if (!ret || buffer.point.ReparseTag != IO_REPARSE_TAG_SYMLINK) | ||
return -1; | ||
|
||
ret = _wrmdir(path); | ||
if (ret == -1) | ||
errno = EACCES; | ||
} | ||
return ret; | ||
} | ||
|
||
/* Windows Unicode support */ | ||
static uintnat windows_unicode_enabled = WINDOWS_UNICODE; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
Unix.symlink works with backwards slashes | ||
Unix.symlink works with forward slashes | ||
Unix.unlink cannot delete directories | ||
Sys.remove cannot delete directories | ||
Unix.unlink can delete symlinks to directories | ||
Unix.unlink can delete symlinks to files | ||
Sys.remove can delete symlinks to directories | ||
Sys.remove can delete symlinks to files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could just
#define caml_unlink unlink
and remove the definition ofunlink_os
from<caml/misc.h>
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need the
unlink_os
definition for ocamlyacc, although it could be moved to ocamlyacc itself?