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.
5 #include "base/platform_file.h"
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"
16 FILE* FdopenPlatformFile(PlatformFile file
, const char* mode
) {
17 if (file
== kInvalidPlatformFileValue
)
19 int fd
= _open_osfhandle(reinterpret_cast<intptr_t>(file
), 0);
22 return _fdopen(fd
, mode
);
25 bool ClosePlatformFile(PlatformFile file
) {
26 base::ThreadRestrictions::AssertIOAllowed();
27 return (CloseHandle(file
) != 0);
30 int64
SeekPlatformFile(PlatformFile file
,
31 PlatformFileWhence whence
,
33 base::ThreadRestrictions::AssertIOAllowed();
34 if (file
== kInvalidPlatformFileValue
|| offset
< 0)
37 LARGE_INTEGER distance
, res
;
38 distance
.QuadPart
= offset
;
39 DWORD move_method
= static_cast<DWORD
>(whence
);
40 if (!SetFilePointerEx(file
, distance
, &res
, move_method
))
45 int ReadPlatformFile(PlatformFile file
, int64 offset
, char* data
, int size
) {
46 base::ThreadRestrictions::AssertIOAllowed();
47 if (file
== kInvalidPlatformFileValue
|| size
< 0)
50 LARGE_INTEGER offset_li
;
51 offset_li
.QuadPart
= offset
;
53 OVERLAPPED overlapped
= {0};
54 overlapped
.Offset
= offset_li
.LowPart
;
55 overlapped
.OffsetHigh
= offset_li
.HighPart
;
58 if (::ReadFile(file
, data
, size
, &bytes_read
, &overlapped
) != 0)
60 if (ERROR_HANDLE_EOF
== GetLastError())
66 int ReadPlatformFileAtCurrentPos(PlatformFile file
, char* data
, int size
) {
67 base::ThreadRestrictions::AssertIOAllowed();
68 if (file
== kInvalidPlatformFileValue
|| size
< 0)
72 if (::ReadFile(file
, data
, size
, &bytes_read
, NULL
) != 0)
74 if (ERROR_HANDLE_EOF
== GetLastError())
80 int ReadPlatformFileNoBestEffort(PlatformFile file
, int64 offset
, char* data
,
82 return ReadPlatformFile(file
, offset
, data
, size
);
85 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file
,
86 char* data
, int size
) {
87 return ReadPlatformFileAtCurrentPos(file
, data
, size
);
90 int WritePlatformFile(PlatformFile file
, int64 offset
,
91 const char* data
, int size
) {
92 base::ThreadRestrictions::AssertIOAllowed();
93 if (file
== kInvalidPlatformFileValue
)
96 LARGE_INTEGER offset_li
;
97 offset_li
.QuadPart
= offset
;
99 OVERLAPPED overlapped
= {0};
100 overlapped
.Offset
= offset_li
.LowPart
;
101 overlapped
.OffsetHigh
= offset_li
.HighPart
;
104 if (::WriteFile(file
, data
, size
, &bytes_written
, &overlapped
) != 0)
105 return bytes_written
;
110 int WritePlatformFileAtCurrentPos(PlatformFile file
, const char* data
,
112 return WritePlatformFile(file
, 0, data
, size
);
115 int WritePlatformFileCurPosNoBestEffort(PlatformFile file
,
116 const char* data
, int size
) {
117 return WritePlatformFile(file
, 0, data
, size
);
120 bool TruncatePlatformFile(PlatformFile file
, int64 length
) {
121 base::ThreadRestrictions::AssertIOAllowed();
122 if (file
== kInvalidPlatformFileValue
)
125 // Get the current file pointer.
126 LARGE_INTEGER file_pointer
;
129 if (::SetFilePointerEx(file
, zero
, &file_pointer
, FILE_CURRENT
) == 0)
132 LARGE_INTEGER length_li
;
133 length_li
.QuadPart
= length
;
134 // If length > file size, SetFilePointerEx() should extend the file
135 // with zeroes on all Windows standard file systems (NTFS, FATxx).
136 if (!::SetFilePointerEx(file
, length_li
, NULL
, FILE_BEGIN
))
139 // Set the new file length and move the file pointer to its old position.
140 // This is consistent with ftruncate()'s behavior, even when the file
141 // pointer points to a location beyond the end of the file.
142 return ((::SetEndOfFile(file
) != 0) &&
143 (::SetFilePointerEx(file
, file_pointer
, NULL
, FILE_BEGIN
) != 0));
146 bool FlushPlatformFile(PlatformFile file
) {
147 base::ThreadRestrictions::AssertIOAllowed();
148 return ((file
!= kInvalidPlatformFileValue
) && ::FlushFileBuffers(file
));
151 bool TouchPlatformFile(PlatformFile file
, const base::Time
& last_access_time
,
152 const base::Time
& last_modified_time
) {
153 base::ThreadRestrictions::AssertIOAllowed();
154 if (file
== kInvalidPlatformFileValue
)
157 FILETIME last_access_filetime
= last_access_time
.ToFileTime();
158 FILETIME last_modified_filetime
= last_modified_time
.ToFileTime();
159 return (::SetFileTime(file
, NULL
, &last_access_filetime
,
160 &last_modified_filetime
) != 0);
163 bool GetPlatformFileInfo(PlatformFile file
, PlatformFileInfo
* info
) {
164 base::ThreadRestrictions::AssertIOAllowed();
168 BY_HANDLE_FILE_INFORMATION file_info
;
169 if (GetFileInformationByHandle(file
, &file_info
) == 0)
173 size
.HighPart
= file_info
.nFileSizeHigh
;
174 size
.LowPart
= file_info
.nFileSizeLow
;
175 info
->size
= size
.QuadPart
;
177 (file_info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
178 info
->is_symbolic_link
= false; // Windows doesn't have symbolic links.
179 info
->last_modified
= base::Time::FromFileTime(file_info
.ftLastWriteTime
);
180 info
->last_accessed
= base::Time::FromFileTime(file_info
.ftLastAccessTime
);
181 info
->creation_time
= base::Time::FromFileTime(file_info
.ftCreationTime
);
185 PlatformFileError
LockPlatformFile(PlatformFile file
) {
186 BOOL result
= LockFile(file
, 0, 0, MAXDWORD
, MAXDWORD
);
188 return LastErrorToPlatformFileError(GetLastError());
189 return PLATFORM_FILE_OK
;
192 PlatformFileError
UnlockPlatformFile(PlatformFile file
) {
193 BOOL result
= UnlockFile(file
, 0, 0, MAXDWORD
, MAXDWORD
);
195 return LastErrorToPlatformFileError(GetLastError());
196 return PLATFORM_FILE_OK
;
199 PlatformFileError
LastErrorToPlatformFileError(DWORD last_error
) {
200 switch (last_error
) {
201 case ERROR_SHARING_VIOLATION
:
202 return PLATFORM_FILE_ERROR_IN_USE
;
203 case ERROR_FILE_EXISTS
:
204 return PLATFORM_FILE_ERROR_EXISTS
;
205 case ERROR_FILE_NOT_FOUND
:
206 case ERROR_PATH_NOT_FOUND
:
207 return PLATFORM_FILE_ERROR_NOT_FOUND
;
208 case ERROR_ACCESS_DENIED
:
209 return PLATFORM_FILE_ERROR_ACCESS_DENIED
;
210 case ERROR_TOO_MANY_OPEN_FILES
:
211 return PLATFORM_FILE_ERROR_TOO_MANY_OPENED
;
212 case ERROR_OUTOFMEMORY
:
213 case ERROR_NOT_ENOUGH_MEMORY
:
214 return PLATFORM_FILE_ERROR_NO_MEMORY
;
215 case ERROR_HANDLE_DISK_FULL
:
216 case ERROR_DISK_FULL
:
217 case ERROR_DISK_RESOURCES_EXHAUSTED
:
218 return PLATFORM_FILE_ERROR_NO_SPACE
;
219 case ERROR_USER_MAPPED_FILE
:
220 return PLATFORM_FILE_ERROR_INVALID_OPERATION
;
221 case ERROR_NOT_READY
:
222 case ERROR_SECTOR_NOT_FOUND
:
223 case ERROR_DEV_NOT_EXIST
:
224 case ERROR_IO_DEVICE
:
225 case ERROR_FILE_CORRUPT
:
226 case ERROR_DISK_CORRUPT
:
227 return PLATFORM_FILE_ERROR_IO
;
229 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
231 return PLATFORM_FILE_ERROR_FAILED
;