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