You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/05/20 17:35:40 UTC
svn commit: r776738 -
/commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c
Author: mturk
Date: Wed May 20 15:35:40 2009
New Revision: 776738
URL: http://svn.apache.org/viewvc?rev=776738&view=rev
Log:
Implement Windows XP symlinks -- directories only
Modified:
commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c?rev=776738&r1=776737&r2=776738&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c Wed May 20 15:35:40 2009
@@ -109,27 +109,111 @@
jboolean rc = JNI_FALSE;
UNREFERENCED_O;
- if (!ACR_HAVE_LATE_DLL_FUNC(CreateSymbolicLinkW)) {
- ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOTIMPL, 0);
- return JNI_FALSE;
- }
+
WITH_WSTR(target) {
WITH_WSTR(lnkname) {
- DWORD dwFlags = 0;
+ char *mpb = NULL;
+ DWORD dwFlags = 0;
size_t tlen = wcslen(J2W(target));
- if (tlen > 0 && J2W(target)[tlen - 1] == L'\\')
+
+ if (ACR_FileTypeGet(NULL, J2W(target)) == ACR_FT_DIR) {
dwFlags = SYMBOLIC_LINK_FLAG_DIRECTORORY;
- if (!CreateSymbolicLinkW(J2W(lnkname), J2W(target), dwFlags)) {
- int err = ACR_GET_OS_ERROR();
- if (ACR_STATUS_IS_EACCES(err)) {
- ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+ }
+ else if (tlen > 0 && (J2W(target)[tlen - 1 ] == L'\\' ||
+ J2W(target)[tlen - 1 ] == L'/')) {
+ dwFlags = SYMBOLIC_LINK_FLAG_DIRECTORORY;
+ }
+ if (ACR_HAVE_LATE_DLL_FUNC(CreateSymbolicLinkW)) {
+ if (!CreateSymbolicLinkW(J2W(lnkname), J2W(target), dwFlags)) {
+ int err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EACCES(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+ }
+ else if (!ACR_STATUS_IS_EEXIST(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, err);
+ }
}
- else if (!ACR_STATUS_IS_EEXIST(err)) {
- ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, err);
+ else
+ rc = JNI_TRUE;
+ }
+ else if (dwFlags == SYMBOLIC_LINK_FLAG_DIRECTORORY) {
+ HANDLE token = NULL;
+ HANDLE hlink = INVALID_HANDLE_VALUE;
+ PREPARSE_DATA_BUFFER rdb;
+ DWORD dlen;
+ wchar_t fpath[ACR_HBUFF_SIZ];
+
+ mpb = ACR_Calloc(_E, THROW_FMARK,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ if (!mpb) {
+ goto bailout;
}
+ if (!GetFullPathNameW(J2W(target), ACR_HBUFF_LEN, fpath, NULL)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO,
+ ACR_GET_OS_ERROR());
+ goto bailout;
+ }
+ tlen = wcslen(fpath);
+ if (tlen > 0 && fpath[tlen - 1] == L'\\') {
+ fpath[--tlen] = L'\0';
+ }
+
+ if (!CreateDirectoryW(J2W(lnkname), NULL)) {
+ /* Failed to create link name directory */
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO,
+ ACR_GET_OS_ERROR());
+ goto bailout;
+ }
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) {
+ TOKEN_PRIVILEGES tp;
+ if (LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) {
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
+ NULL, NULL);
+ }
+ CloseHandle(token);
+ }
+ hlink = CreateFileW(J2W(lnkname),
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ if (hlink == INVALID_HANDLE_VALUE) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO,
+ ACR_GET_OS_ERROR());
+ goto bailout;
+ }
+ rdb = (PREPARSE_DATA_BUFFER)mpb;
+ rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+
+ wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
+ wcscat(rdb->MountPointReparseBuffer.PathBuffer, fpath);
+ tlen = wcslen(rdb->MountPointReparseBuffer.PathBuffer);
+
+ rdb->MountPointReparseBuffer.SubstituteNameLength = tlen * sizeof(wchar_t);
+ rdb->MountPointReparseBuffer.PrintNameOffset = (tlen + 1) * sizeof(wchar_t);
+ rdb->ReparseDataLength = sizeof(rdb->MountPointReparseBuffer) + ((tlen + 1) * sizeof(wchar_t));
+
+ if (!DeviceIoControl(hlink, FSCTL_SET_REPARSE_POINT,
+ rdb, rdb->ReparseDataLength + 8,
+ NULL, 0, &dlen, NULL)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO,
+ ACR_GET_OS_ERROR());
+ }
+ else {
+ rc = JNI_TRUE;
+ }
+ CloseHandle(hlink);
}
- else
- rc = JNI_TRUE;
+ else {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOTIMPL, 0);
+ }
+ bailout:
+ if (mpb)
+ free(mpb);
} END_WITH_WSTR(lnkname);
} END_WITH_WSTR(target);