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

Unified Diff: runtime/bin/file_win.cc

Issue 12812010: dart:io | Add Link.targetSync on all platforms. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Improve copying of target string on Windows. 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
Index: runtime/bin/file_win.cc
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index b23049dce5bfc7241347d89db5fae8060409d6d5..3101e6658f38bf9d28cdbb499e3192f73a2b685f 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -279,6 +279,73 @@ off_t File::LengthFromPath(const char* name) {
}
+char* File::LinkTarget(const char* pathname) {
+ const wchar_t* name = StringUtils::Utf8ToWide(pathname);
+ HANDLE dir_handle = CreateFileW(
+ name,
+ GENERIC_READ,
+ 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 NULL;
+ }
+
+ int reparse_data_buffer_size =
+ sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR;
+ REPARSE_DATA_BUFFER* reparse_data_buffer =
+ static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1));
+ DWORD received_bytes;
+ int result = DeviceIoControl(
+ dir_handle,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ 0,
+ reparse_data_buffer,
+ reparse_data_buffer_size,
+ &received_bytes,
+ NULL);
+ if (CloseHandle(dir_handle) == 0) return NULL;
Søren Gjesse 2013/03/18 12:28:03 Here it seems like we are clearing the last error
Bill Hesse 2013/03/18 16:13:27 Yes. Fixed.
+ if (result == 0) return NULL;
+ if (reparse_data_buffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) {
Søren Gjesse 2013/03/18 12:28:03 Here GetLastError will return NOERROR, so we get a
Bill Hesse 2013/03/18 16:13:27 Now we are returning Not a Reparse Point.
+ return NULL;
+ }
+ wchar_t* target = reparse_data_buffer->MountPointReparseBuffer.PathBuffer +
+ reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset;
+ size_t target_length =
+ reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength;
+ // Remove "\??\" from beginning of target.
+ if (target_length <= 4 || wcsncmp(L"\\??\\", target, 4) != 0) return NULL;
Søren Gjesse 2013/03/18 12:28:03 Ditto.
Bill Hesse 2013/03/18 16:13:27 Changed. Now, we just skip removing \??\ if it is
+ int utf8_length = WideCharToMultiByte(CP_UTF8,
Søren Gjesse 2013/03/18 12:28:03 Indentation.
+ 0,
+ target + 4,
+ target_length - 4,
+ NULL,
+ 0,
+ NULL,
+ NULL);
Søren Gjesse 2013/03/18 12:28:03 Can this call fail?
Bill Hesse 2013/03/18 16:13:27 If it fails, it returns 0, and the next call to it
+ char* utf8_target = reinterpret_cast<char*>(malloc(utf8_length + 1));
+ if (0 == WideCharToMultiByte(CP_UTF8,
+ 0,
+ target + 4,
+ target_length - 4,
+ utf8_target,
+ utf8_length,
+ NULL,
+ NULL)) {
+ free(reparse_data_buffer);
+ free(utf8_target);
Søren Gjesse 2013/03/18 12:28:03 Set an error code?
Bill Hesse 2013/03/18 16:13:27 Done.
+ return NULL;
+ }
+ utf8_target[utf8_length] = '\0';
+ free(reparse_data_buffer);
+ return utf8_target;
+}
+
+
time_t File::LastModified(const char* name) {
struct _stat st;
const wchar_t* system_name = StringUtils::Utf8ToWide(name);

Powered by Google App Engine
This is Rietveld 408576698