OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 <io.h> | |
8 | |
9 #include "base/files/file_path.h" | |
10 #include "base/logging.h" | |
11 #include "base/metrics/sparse_histogram.h" | |
12 #include "base/threading/thread_restrictions.h" | |
13 | |
14 namespace base { | |
15 | |
16 bool ClosePlatformFile(PlatformFile file) { | |
17 base::ThreadRestrictions::AssertIOAllowed(); | |
18 return (CloseHandle(file) != 0); | |
19 } | |
20 | |
21 int64 SeekPlatformFile(PlatformFile file, | |
22 PlatformFileWhence whence, | |
23 int64 offset) { | |
24 base::ThreadRestrictions::AssertIOAllowed(); | |
25 if (file == kInvalidPlatformFileValue || offset < 0) | |
26 return -1; | |
27 | |
28 LARGE_INTEGER distance, res; | |
29 distance.QuadPart = offset; | |
30 DWORD move_method = static_cast<DWORD>(whence); | |
31 if (!SetFilePointerEx(file, distance, &res, move_method)) | |
32 return -1; | |
33 return res.QuadPart; | |
34 } | |
35 | |
36 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { | |
37 base::ThreadRestrictions::AssertIOAllowed(); | |
38 if (file == kInvalidPlatformFileValue || size < 0) | |
39 return -1; | |
40 | |
41 LARGE_INTEGER offset_li; | |
42 offset_li.QuadPart = offset; | |
43 | |
44 OVERLAPPED overlapped = {0}; | |
45 overlapped.Offset = offset_li.LowPart; | |
46 overlapped.OffsetHigh = offset_li.HighPart; | |
47 | |
48 DWORD bytes_read; | |
49 if (::ReadFile(file, data, size, &bytes_read, &overlapped) != 0) | |
50 return bytes_read; | |
51 if (ERROR_HANDLE_EOF == GetLastError()) | |
52 return 0; | |
53 | |
54 return -1; | |
55 } | |
56 | |
57 int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) { | |
58 base::ThreadRestrictions::AssertIOAllowed(); | |
59 if (file == kInvalidPlatformFileValue || size < 0) | |
60 return -1; | |
61 | |
62 DWORD bytes_read; | |
63 if (::ReadFile(file, data, size, &bytes_read, NULL) != 0) | |
64 return bytes_read; | |
65 if (ERROR_HANDLE_EOF == GetLastError()) | |
66 return 0; | |
67 | |
68 return -1; | |
69 } | |
70 | |
71 int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, char* data, | |
72 int size) { | |
73 return ReadPlatformFile(file, offset, data, size); | |
74 } | |
75 | |
76 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, | |
77 char* data, int size) { | |
78 return ReadPlatformFileAtCurrentPos(file, data, size); | |
79 } | |
80 | |
81 int WritePlatformFile(PlatformFile file, int64 offset, | |
82 const char* data, int size) { | |
83 base::ThreadRestrictions::AssertIOAllowed(); | |
84 if (file == kInvalidPlatformFileValue) | |
85 return -1; | |
86 | |
87 LARGE_INTEGER offset_li; | |
88 offset_li.QuadPart = offset; | |
89 | |
90 OVERLAPPED overlapped = {0}; | |
91 overlapped.Offset = offset_li.LowPart; | |
92 overlapped.OffsetHigh = offset_li.HighPart; | |
93 | |
94 DWORD bytes_written; | |
95 if (::WriteFile(file, data, size, &bytes_written, &overlapped) != 0) | |
96 return bytes_written; | |
97 | |
98 return -1; | |
99 } | |
100 | |
101 int WritePlatformFileAtCurrentPos(PlatformFile file, const char* data, | |
102 int size) { | |
103 return WritePlatformFile(file, 0, data, size); | |
104 } | |
105 | |
106 int WritePlatformFileCurPosNoBestEffort(PlatformFile file, | |
107 const char* data, int size) { | |
108 return WritePlatformFile(file, 0, data, size); | |
109 } | |
110 | |
111 bool TruncatePlatformFile(PlatformFile file, int64 length) { | |
112 base::ThreadRestrictions::AssertIOAllowed(); | |
113 if (file == kInvalidPlatformFileValue) | |
114 return false; | |
115 | |
116 // Get the current file pointer. | |
117 LARGE_INTEGER file_pointer; | |
118 LARGE_INTEGER zero; | |
119 zero.QuadPart = 0; | |
120 if (::SetFilePointerEx(file, zero, &file_pointer, FILE_CURRENT) == 0) | |
121 return false; | |
122 | |
123 LARGE_INTEGER length_li; | |
124 length_li.QuadPart = length; | |
125 // If length > file size, SetFilePointerEx() should extend the file | |
126 // with zeroes on all Windows standard file systems (NTFS, FATxx). | |
127 if (!::SetFilePointerEx(file, length_li, NULL, FILE_BEGIN)) | |
128 return false; | |
129 | |
130 // Set the new file length and move the file pointer to its old position. | |
131 // This is consistent with ftruncate()'s behavior, even when the file | |
132 // pointer points to a location beyond the end of the file. | |
133 return ((::SetEndOfFile(file) != 0) && | |
134 (::SetFilePointerEx(file, file_pointer, NULL, FILE_BEGIN) != 0)); | |
135 } | |
136 | |
137 bool FlushPlatformFile(PlatformFile file) { | |
138 base::ThreadRestrictions::AssertIOAllowed(); | |
139 return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file)); | |
140 } | |
141 | |
142 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time, | |
143 const base::Time& last_modified_time) { | |
144 base::ThreadRestrictions::AssertIOAllowed(); | |
145 if (file == kInvalidPlatformFileValue) | |
146 return false; | |
147 | |
148 FILETIME last_access_filetime = last_access_time.ToFileTime(); | |
149 FILETIME last_modified_filetime = last_modified_time.ToFileTime(); | |
150 return (::SetFileTime(file, NULL, &last_access_filetime, | |
151 &last_modified_filetime) != 0); | |
152 } | |
153 | |
154 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { | |
155 base::ThreadRestrictions::AssertIOAllowed(); | |
156 if (!info) | |
157 return false; | |
158 | |
159 BY_HANDLE_FILE_INFORMATION file_info; | |
160 if (GetFileInformationByHandle(file, &file_info) == 0) | |
161 return false; | |
162 | |
163 LARGE_INTEGER size; | |
164 size.HighPart = file_info.nFileSizeHigh; | |
165 size.LowPart = file_info.nFileSizeLow; | |
166 info->size = size.QuadPart; | |
167 info->is_directory = | |
168 (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; | |
169 info->is_symbolic_link = false; // Windows doesn't have symbolic links. | |
170 info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime); | |
171 info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime); | |
172 info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime); | |
173 return true; | |
174 } | |
175 | |
176 PlatformFileError LockPlatformFile(PlatformFile file) { | |
177 BOOL result = LockFile(file, 0, 0, MAXDWORD, MAXDWORD); | |
178 if (!result) | |
179 return LastErrorToPlatformFileError(GetLastError()); | |
180 return PLATFORM_FILE_OK; | |
181 } | |
182 | |
183 PlatformFileError UnlockPlatformFile(PlatformFile file) { | |
184 BOOL result = UnlockFile(file, 0, 0, MAXDWORD, MAXDWORD); | |
185 if (!result) | |
186 return LastErrorToPlatformFileError(GetLastError()); | |
187 return PLATFORM_FILE_OK; | |
188 } | |
189 | |
190 PlatformFileError LastErrorToPlatformFileError(DWORD last_error) { | |
191 switch (last_error) { | |
192 case ERROR_SHARING_VIOLATION: | |
193 return PLATFORM_FILE_ERROR_IN_USE; | |
194 case ERROR_FILE_EXISTS: | |
195 return PLATFORM_FILE_ERROR_EXISTS; | |
196 case ERROR_FILE_NOT_FOUND: | |
197 case ERROR_PATH_NOT_FOUND: | |
198 return PLATFORM_FILE_ERROR_NOT_FOUND; | |
199 case ERROR_ACCESS_DENIED: | |
200 return PLATFORM_FILE_ERROR_ACCESS_DENIED; | |
201 case ERROR_TOO_MANY_OPEN_FILES: | |
202 return PLATFORM_FILE_ERROR_TOO_MANY_OPENED; | |
203 case ERROR_OUTOFMEMORY: | |
204 case ERROR_NOT_ENOUGH_MEMORY: | |
205 return PLATFORM_FILE_ERROR_NO_MEMORY; | |
206 case ERROR_HANDLE_DISK_FULL: | |
207 case ERROR_DISK_FULL: | |
208 case ERROR_DISK_RESOURCES_EXHAUSTED: | |
209 return PLATFORM_FILE_ERROR_NO_SPACE; | |
210 case ERROR_USER_MAPPED_FILE: | |
211 return PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
212 case ERROR_NOT_READY: | |
213 case ERROR_SECTOR_NOT_FOUND: | |
214 case ERROR_DEV_NOT_EXIST: | |
215 case ERROR_IO_DEVICE: | |
216 case ERROR_FILE_CORRUPT: | |
217 case ERROR_DISK_CORRUPT: | |
218 return PLATFORM_FILE_ERROR_IO; | |
219 default: | |
220 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows", | |
221 last_error); | |
222 return PLATFORM_FILE_ERROR_FAILED; | |
223 } | |
224 } | |
225 | |
226 } // namespace base | |
OLD | NEW |