OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
7 | 7 |
8 #include "bin/file.h" | 8 #include "bin/file.h" |
9 | 9 |
10 #include <fcntl.h> // NOLINT | 10 #include <fcntl.h> // NOLINT |
11 #include <io.h> // NOLINT | 11 #include <io.h> // NOLINT |
12 #include <stdio.h> // NOLINT | 12 #include <stdio.h> // NOLINT |
13 #include <string.h> // NOLINT | 13 #include <string.h> // NOLINT |
14 #include <sys/stat.h> // NOLINT | 14 #include <sys/stat.h> // NOLINT |
| 15 #include <WinIoCtl.h> // NOLINT |
15 | 16 |
16 #include "bin/builtin.h" | 17 #include "bin/builtin.h" |
17 #include "bin/log.h" | 18 #include "bin/log.h" |
18 | 19 |
19 class FileHandle { | 20 class FileHandle { |
20 public: | 21 public: |
21 explicit FileHandle(int fd) : fd_(fd) { } | 22 explicit FileHandle(int fd) : fd_(fd) { } |
22 ~FileHandle() { } | 23 ~FileHandle() { } |
23 int fd() const { return fd_; } | 24 int fd() const { return fd_; } |
24 void set_fd(int fd) { fd_ = fd; } | 25 void set_fd(int fd) { fd_ = fd; } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 const wchar_t* system_name = StringUtils::Utf8ToWide(name); | 148 const wchar_t* system_name = StringUtils::Utf8ToWide(name); |
148 int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666); | 149 int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666); |
149 free(const_cast<wchar_t*>(system_name)); | 150 free(const_cast<wchar_t*>(system_name)); |
150 if (fd < 0) { | 151 if (fd < 0) { |
151 return false; | 152 return false; |
152 } | 153 } |
153 return (close(fd) == 0); | 154 return (close(fd) == 0); |
154 } | 155 } |
155 | 156 |
156 | 157 |
| 158 // This structure is needed for creating and reading Junctions. |
| 159 typedef struct _REPARSE_DATA_BUFFER { |
| 160 ULONG ReparseTag; |
| 161 USHORT ReparseDataLength; |
| 162 USHORT Reserved; |
| 163 |
| 164 union { |
| 165 struct { |
| 166 USHORT SubstituteNameOffset; |
| 167 USHORT SubstituteNameLength; |
| 168 USHORT PrintNameOffset; |
| 169 USHORT PrintNameLength; |
| 170 WCHAR PathBuffer[1]; |
| 171 } SymbolicLinkReparseBuffer; |
| 172 |
| 173 struct { |
| 174 USHORT SubstituteNameOffset; |
| 175 USHORT SubstituteNameLength; |
| 176 USHORT PrintNameOffset; |
| 177 USHORT PrintNameLength; |
| 178 WCHAR PathBuffer[1]; |
| 179 } MountPointReparseBuffer; |
| 180 |
| 181 struct { |
| 182 UCHAR DataBuffer[1]; |
| 183 } GenericReparseBuffer; |
| 184 }; |
| 185 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; |
| 186 |
| 187 |
| 188 static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT; |
| 189 static const int kMountPointHeaderSize = 4 * sizeof USHORT; |
| 190 |
| 191 |
| 192 bool File::CreateLink(const char* utf8_name, const char* utf8_target) { |
| 193 const wchar_t* name = StringUtils::Utf8ToWide(utf8_name); |
| 194 int create_status = CreateDirectoryW(name, NULL); |
| 195 // If the directory already existed, treat it as a success. |
| 196 if (create_status == 0 && |
| 197 (GetLastError() != ERROR_ALREADY_EXISTS || |
| 198 (GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0)) { |
| 199 free(const_cast<wchar_t*>(name)); |
| 200 return false; |
| 201 } |
| 202 |
| 203 HANDLE dir_handle = CreateFileW( |
| 204 name, |
| 205 GENERIC_READ | GENERIC_WRITE, |
| 206 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 207 NULL, |
| 208 OPEN_EXISTING, |
| 209 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| 210 NULL); |
| 211 free(const_cast<wchar_t*>(name)); |
| 212 if (dir_handle == INVALID_HANDLE_VALUE) { |
| 213 return false; |
| 214 } |
| 215 |
| 216 const wchar_t* target = StringUtils::Utf8ToWide(utf8_target); |
| 217 int target_len = wcslen(target); |
| 218 if (target_len > MAX_PATH - 1) { |
| 219 free(const_cast<wchar_t*>(target)); |
| 220 CloseHandle(dir_handle); |
| 221 return false; |
| 222 } |
| 223 |
| 224 int reparse_data_buffer_size = |
| 225 sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR; |
| 226 REPARSE_DATA_BUFFER* reparse_data_buffer = |
| 227 static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1)); |
| 228 reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; |
| 229 wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, target); |
| 230 wcscpy( |
| 231 reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1, |
| 232 target); |
| 233 reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0; |
| 234 reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength = |
| 235 target_len * sizeof WCHAR; |
| 236 reparse_data_buffer->MountPointReparseBuffer.PrintNameOffset = |
| 237 (target_len + 1) * sizeof WCHAR; |
| 238 reparse_data_buffer->MountPointReparseBuffer.PrintNameLength = |
| 239 target_len * sizeof WCHAR; |
| 240 reparse_data_buffer->ReparseDataLength = |
| 241 (target_len + 1) * 2 * sizeof WCHAR + kMountPointHeaderSize; |
| 242 DWORD dummy_received_bytes; |
| 243 int result = DeviceIoControl( |
| 244 dir_handle, |
| 245 FSCTL_SET_REPARSE_POINT, |
| 246 reparse_data_buffer, |
| 247 reparse_data_buffer->ReparseDataLength + kReparseDataHeaderSize, |
| 248 NULL, |
| 249 0, |
| 250 &dummy_received_bytes, |
| 251 NULL); |
| 252 if (CloseHandle(dir_handle) == 0) return false; |
| 253 free(const_cast<wchar_t*>(target)); |
| 254 free(reparse_data_buffer); |
| 255 return (result != 0); |
| 256 } |
| 257 |
| 258 |
157 bool File::Delete(const char* name) { | 259 bool File::Delete(const char* name) { |
158 const wchar_t* system_name = StringUtils::Utf8ToWide(name); | 260 const wchar_t* system_name = StringUtils::Utf8ToWide(name); |
159 int status = _wremove(system_name); | 261 int status = _wremove(system_name); |
160 free(const_cast<wchar_t*>(system_name)); | 262 free(const_cast<wchar_t*>(system_name)); |
161 if (status == -1) { | 263 if (status == -1) { |
162 return false; | 264 return false; |
163 } | 265 } |
164 return true; | 266 return true; |
165 } | 267 } |
166 | 268 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 374 |
273 | 375 |
274 File::Type File::GetType(const char* pathname, bool follow_links) { | 376 File::Type File::GetType(const char* pathname, bool follow_links) { |
275 const wchar_t* name = StringUtils::Utf8ToWide(pathname); | 377 const wchar_t* name = StringUtils::Utf8ToWide(pathname); |
276 WIN32_FIND_DATAW file_data; | 378 WIN32_FIND_DATAW file_data; |
277 HANDLE find_handle = FindFirstFileW(name, &file_data); | 379 HANDLE find_handle = FindFirstFileW(name, &file_data); |
278 if (find_handle == INVALID_HANDLE_VALUE) { | 380 if (find_handle == INVALID_HANDLE_VALUE) { |
279 // TODO(whesse): Distinguish other errors from does not exist. | 381 // TODO(whesse): Distinguish other errors from does not exist. |
280 return File::kDoesNotExist; | 382 return File::kDoesNotExist; |
281 } | 383 } |
| 384 FindClose(find_handle); |
282 DWORD attributes = file_data.dwFileAttributes; | 385 DWORD attributes = file_data.dwFileAttributes; |
283 if (!follow_links && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { | 386 if (!follow_links && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { |
284 DWORD reparse_tag = file_data.dwReserved0; | 387 DWORD reparse_tag = file_data.dwReserved0; |
285 if (reparse_tag == IO_REPARSE_TAG_SYMLINK || | 388 if (reparse_tag == IO_REPARSE_TAG_SYMLINK || |
286 reparse_tag == IO_REPARSE_TAG_MOUNT_POINT) { | 389 reparse_tag == IO_REPARSE_TAG_MOUNT_POINT) { |
287 return File::kIsLink; | 390 return File::kIsLink; |
288 } else { | 391 } else { |
289 return File::kDoesNotExist; | 392 return File::kDoesNotExist; |
290 } | 393 } |
291 } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 394 } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
292 return File::kIsDirectory; | 395 return File::kIsDirectory; |
293 } else { | 396 } else { |
294 return File::kIsFile; | 397 return File::kIsFile; |
295 } | 398 } |
296 } | 399 } |
297 | 400 |
298 #endif // defined(TARGET_OS_WINDOWS) | 401 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |