platform_file_win.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/platform_file.h" 6 7#include "base/file_path.h" 8#include "base/logging.h" 9#include "base/thread_restrictions.h" 10 11namespace base { 12 13PlatformFile CreatePlatformFile(const FilePath& name, 14 int flags, 15 bool* created, 16 PlatformFileError* error_code) { 17 base::ThreadRestrictions::AssertIOAllowed(); 18 19 DWORD disposition = 0; 20 21 if (flags & PLATFORM_FILE_OPEN) 22 disposition = OPEN_EXISTING; 23 24 if (flags & PLATFORM_FILE_CREATE) { 25 DCHECK(!disposition); 26 disposition = CREATE_NEW; 27 } 28 29 if (flags & PLATFORM_FILE_OPEN_ALWAYS) { 30 DCHECK(!disposition); 31 disposition = OPEN_ALWAYS; 32 } 33 34 if (flags & PLATFORM_FILE_CREATE_ALWAYS) { 35 DCHECK(!disposition); 36 disposition = CREATE_ALWAYS; 37 } 38 39 if (flags & PLATFORM_FILE_TRUNCATE) { 40 DCHECK(!disposition); 41 DCHECK(flags & PLATFORM_FILE_WRITE); 42 disposition = TRUNCATE_EXISTING; 43 } 44 45 if (!disposition) { 46 NOTREACHED(); 47 return NULL; 48 } 49 50 DWORD access = (flags & PLATFORM_FILE_READ) ? GENERIC_READ : 0; 51 if (flags & PLATFORM_FILE_WRITE) 52 access |= GENERIC_WRITE; 53 if (flags & PLATFORM_FILE_WRITE_ATTRIBUTES) 54 access |= FILE_WRITE_ATTRIBUTES; 55 56 DWORD sharing = (flags & PLATFORM_FILE_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ; 57 if (!(flags & PLATFORM_FILE_EXCLUSIVE_WRITE)) 58 sharing |= FILE_SHARE_WRITE; 59 60 DWORD create_flags = 0; 61 if (flags & PLATFORM_FILE_ASYNC) 62 create_flags |= FILE_FLAG_OVERLAPPED; 63 if (flags & PLATFORM_FILE_TEMPORARY) 64 create_flags |= FILE_ATTRIBUTE_TEMPORARY; 65 if (flags & PLATFORM_FILE_HIDDEN) 66 create_flags |= FILE_ATTRIBUTE_HIDDEN; 67 if (flags & PLATFORM_FILE_DELETE_ON_CLOSE) 68 create_flags |= FILE_FLAG_DELETE_ON_CLOSE; 69 70 HANDLE file = CreateFile(name.value().c_str(), access, sharing, NULL, 71 disposition, create_flags, NULL); 72 73 if (created && (INVALID_HANDLE_VALUE != file)) { 74 if (flags & (PLATFORM_FILE_OPEN_ALWAYS)) 75 *created = (ERROR_ALREADY_EXISTS != GetLastError()); 76 else if (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)) 77 *created = true; 78 } 79 80 if (error_code) { 81 if (file != kInvalidPlatformFileValue) 82 *error_code = PLATFORM_FILE_OK; 83 else { 84 DWORD last_error = GetLastError(); 85 switch (last_error) { 86 case ERROR_SHARING_VIOLATION: 87 *error_code = PLATFORM_FILE_ERROR_IN_USE; 88 break; 89 case ERROR_FILE_EXISTS: 90 *error_code = PLATFORM_FILE_ERROR_EXISTS; 91 break; 92 case ERROR_FILE_NOT_FOUND: 93 *error_code = PLATFORM_FILE_ERROR_NOT_FOUND; 94 break; 95 case ERROR_ACCESS_DENIED: 96 *error_code = PLATFORM_FILE_ERROR_ACCESS_DENIED; 97 break; 98 default: 99 *error_code = PLATFORM_FILE_ERROR_FAILED; 100 } 101 } 102 } 103 104 return file; 105} 106 107PlatformFile CreatePlatformFile(const std::wstring& name, int flags, 108 bool* created) { 109 return CreatePlatformFile(FilePath::FromWStringHack(name), flags, 110 created, NULL); 111} 112 113bool ClosePlatformFile(PlatformFile file) { 114 base::ThreadRestrictions::AssertIOAllowed(); 115 return (CloseHandle(file) != 0); 116} 117 118int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { 119 base::ThreadRestrictions::AssertIOAllowed(); 120 if (file == kInvalidPlatformFileValue) 121 return -1; 122 123 LARGE_INTEGER offset_li; 124 offset_li.QuadPart = offset; 125 126 OVERLAPPED overlapped = {0}; 127 overlapped.Offset = offset_li.LowPart; 128 overlapped.OffsetHigh = offset_li.HighPart; 129 130 DWORD bytes_read; 131 if (::ReadFile(file, data, size, &bytes_read, &overlapped) != 0) 132 return bytes_read; 133 else if (ERROR_HANDLE_EOF == GetLastError()) 134 return 0; 135 136 return -1; 137} 138 139int WritePlatformFile(PlatformFile file, int64 offset, 140 const char* data, int size) { 141 base::ThreadRestrictions::AssertIOAllowed(); 142 if (file == kInvalidPlatformFileValue) 143 return -1; 144 145 LARGE_INTEGER offset_li; 146 offset_li.QuadPart = offset; 147 148 OVERLAPPED overlapped = {0}; 149 overlapped.Offset = offset_li.LowPart; 150 overlapped.OffsetHigh = offset_li.HighPart; 151 152 DWORD bytes_written; 153 if (::WriteFile(file, data, size, &bytes_written, &overlapped) != 0) 154 return bytes_written; 155 156 return -1; 157} 158 159bool TruncatePlatformFile(PlatformFile file, int64 length) { 160 base::ThreadRestrictions::AssertIOAllowed(); 161 if (file == kInvalidPlatformFileValue) 162 return false; 163 164 // Get the current file pointer. 165 LARGE_INTEGER file_pointer; 166 LARGE_INTEGER zero; 167 zero.QuadPart = 0; 168 if (::SetFilePointerEx(file, zero, &file_pointer, FILE_CURRENT) == 0) 169 return false; 170 171 LARGE_INTEGER length_li; 172 length_li.QuadPart = length; 173 // If length > file size, SetFilePointerEx() should extend the file 174 // with zeroes on all Windows standard file systems (NTFS, FATxx). 175 if (!::SetFilePointerEx(file, length_li, NULL, FILE_BEGIN)) 176 return false; 177 178 // Set the new file length and move the file pointer to its old position. 179 // This is consistent with ftruncate()'s behavior, even when the file 180 // pointer points to a location beyond the end of the file. 181 return ((::SetEndOfFile(file) != 0) && 182 (::SetFilePointerEx(file, file_pointer, NULL, FILE_BEGIN) != 0)); 183} 184 185bool FlushPlatformFile(PlatformFile file) { 186 base::ThreadRestrictions::AssertIOAllowed(); 187 return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file)); 188} 189 190bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time, 191 const base::Time& last_modified_time) { 192 base::ThreadRestrictions::AssertIOAllowed(); 193 if (file == kInvalidPlatformFileValue) 194 return false; 195 196 FILETIME last_access_filetime = last_access_time.ToFileTime(); 197 FILETIME last_modified_filetime = last_modified_time.ToFileTime(); 198 return (::SetFileTime(file, NULL, &last_access_filetime, 199 &last_modified_filetime) != 0); 200} 201 202bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { 203 base::ThreadRestrictions::AssertIOAllowed(); 204 if (!info) 205 return false; 206 207 BY_HANDLE_FILE_INFORMATION file_info; 208 if (GetFileInformationByHandle(file, &file_info) == 0) 209 return false; 210 211 LARGE_INTEGER size; 212 size.HighPart = file_info.nFileSizeHigh; 213 size.LowPart = file_info.nFileSizeLow; 214 info->size = size.QuadPart; 215 info->is_directory = 216 file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0; 217 info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime); 218 info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime); 219 info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime); 220 return true; 221} 222 223} // namespace disk_cache 224