Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(662)

Unified Diff: runtime/bin/file_win.cc

Issue 12691002: dart:io | Add Link class, as sibling to File and Directory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix Windows errors Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/file_patch.dart ('k') | sdk/lib/_internal/compiler/implementation/lib/io_patch.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/file_win.cc
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 1c22ededcf24a42cf4e9f11b88c82581a71948d3..2e255293e7bd632d4427bf20d81fb1c7c5f99e81 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -12,6 +12,7 @@
#include <stdio.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/stat.h> // NOLINT
+#include <WinIoCtl.h> // NOLINT
#include "bin/builtin.h"
#include "bin/log.h"
@@ -154,6 +155,107 @@ bool File::Create(const char* name) {
}
+// This structure is needed for creating and reading Junctions.
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ 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;
+
+
+static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT;
+static const int kMountPointHeaderSize = 4 * sizeof USHORT;
+
+
+bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
+ const wchar_t* name = StringUtils::Utf8ToWide(utf8_name);
+ int create_status = CreateDirectoryW(name, NULL);
+ // If the directory already existed, treat it as a success.
+ if (create_status == 0 &&
+ (GetLastError() != ERROR_ALREADY_EXISTS ||
+ (GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
+ free(const_cast<wchar_t*>(name));
+ return false;
+ }
+
+ HANDLE dir_handle = CreateFileW(
+ name,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
+ NULL);
+ free(const_cast<wchar_t*>(name));
+ if (dir_handle == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ const wchar_t* target = StringUtils::Utf8ToWide(utf8_target);
+ int target_len = wcslen(target);
+ if (target_len > MAX_PATH - 1) {
+ free(const_cast<wchar_t*>(target));
+ CloseHandle(dir_handle);
+ return false;
+ }
+
+ int reparse_data_buffer_size =
+ sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR;
+ REPARSE_DATA_BUFFER* reparse_data_buffer =
+ static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1));
+ reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, target);
+ wcscpy(
+ reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1,
+ target);
+ reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0;
+ reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength =
+ target_len * sizeof WCHAR;
+ reparse_data_buffer->MountPointReparseBuffer.PrintNameOffset =
+ (target_len + 1) * sizeof WCHAR;
+ reparse_data_buffer->MountPointReparseBuffer.PrintNameLength =
+ target_len * sizeof WCHAR;
+ reparse_data_buffer->ReparseDataLength =
+ (target_len + 1) * 2 * sizeof WCHAR + kMountPointHeaderSize;
+ DWORD dummy_received_bytes;
+ int result = DeviceIoControl(
+ dir_handle,
+ FSCTL_SET_REPARSE_POINT,
+ reparse_data_buffer,
+ reparse_data_buffer->ReparseDataLength + kReparseDataHeaderSize,
+ NULL,
+ 0,
+ &dummy_received_bytes,
+ NULL);
+ if (CloseHandle(dir_handle) == 0) return false;
+ free(const_cast<wchar_t*>(target));
+ free(reparse_data_buffer);
+ return (result != 0);
+}
+
+
bool File::Delete(const char* name) {
const wchar_t* system_name = StringUtils::Utf8ToWide(name);
int status = _wremove(system_name);
@@ -279,6 +381,7 @@ File::Type File::GetType(const char* pathname, bool follow_links) {
// TODO(whesse): Distinguish other errors from does not exist.
return File::kDoesNotExist;
}
+ FindClose(find_handle);
DWORD attributes = file_data.dwFileAttributes;
if (!follow_links && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
DWORD reparse_tag = file_data.dwReserved0;
« no previous file with comments | « runtime/bin/file_patch.dart ('k') | sdk/lib/_internal/compiler/implementation/lib/io_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698