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"
7 #include "base/file_path.h"
8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h"
12 PlatformFile
CreatePlatformFileUnsafe(const FilePath
& name
,
15 PlatformFileError
* error
) {
16 base::ThreadRestrictions::AssertIOAllowed();
18 DWORD disposition
= 0;
22 if (flags
& PLATFORM_FILE_OPEN
)
23 disposition
= OPEN_EXISTING
;
25 if (flags
& PLATFORM_FILE_CREATE
) {
27 disposition
= CREATE_NEW
;
30 if (flags
& PLATFORM_FILE_OPEN_ALWAYS
) {
32 disposition
= OPEN_ALWAYS
;
35 if (flags
& PLATFORM_FILE_CREATE_ALWAYS
) {
37 disposition
= CREATE_ALWAYS
;
40 if (flags
& PLATFORM_FILE_OPEN_TRUNCATED
) {
42 DCHECK(flags
& PLATFORM_FILE_WRITE
);
43 disposition
= TRUNCATE_EXISTING
;
51 DWORD access
= (flags
& PLATFORM_FILE_READ
) ? GENERIC_READ
: 0;
52 if (flags
& PLATFORM_FILE_WRITE
)
53 access
|= GENERIC_WRITE
;
54 if (flags
& PLATFORM_FILE_WRITE_ATTRIBUTES
)
55 access
|= FILE_WRITE_ATTRIBUTES
;
57 DWORD sharing
= (flags
& PLATFORM_FILE_EXCLUSIVE_READ
) ? 0 : FILE_SHARE_READ
;
58 if (!(flags
& PLATFORM_FILE_EXCLUSIVE_WRITE
))
59 sharing
|= FILE_SHARE_WRITE
;
60 if (flags
& PLATFORM_FILE_SHARE_DELETE
)
61 sharing
|= FILE_SHARE_DELETE
;
63 DWORD create_flags
= 0;
64 if (flags
& PLATFORM_FILE_ASYNC
)
65 create_flags
|= FILE_FLAG_OVERLAPPED
;
66 if (flags
& PLATFORM_FILE_TEMPORARY
)
67 create_flags
|= FILE_ATTRIBUTE_TEMPORARY
;
68 if (flags
& PLATFORM_FILE_HIDDEN
)
69 create_flags
|= FILE_ATTRIBUTE_HIDDEN
;
70 if (flags
& PLATFORM_FILE_DELETE_ON_CLOSE
)
71 create_flags
|= FILE_FLAG_DELETE_ON_CLOSE
;
72 if (flags
& PLATFORM_FILE_BACKUP_SEMANTICS
)
73 create_flags
|= FILE_FLAG_BACKUP_SEMANTICS
;
75 HANDLE file
= CreateFile(name
.value().c_str(), access
, sharing
, NULL
,
76 disposition
, create_flags
, NULL
);
78 if (created
&& (INVALID_HANDLE_VALUE
!= file
)) {
79 if (flags
& (PLATFORM_FILE_OPEN_ALWAYS
))
80 *created
= (ERROR_ALREADY_EXISTS
!= GetLastError());
81 else if (flags
& (PLATFORM_FILE_CREATE_ALWAYS
| PLATFORM_FILE_CREATE
))
86 if (file
!= kInvalidPlatformFileValue
)
87 *error
= PLATFORM_FILE_OK
;
89 DWORD last_error
= GetLastError();
91 case ERROR_SHARING_VIOLATION
:
92 *error
= PLATFORM_FILE_ERROR_IN_USE
;
94 case ERROR_FILE_EXISTS
:
95 *error
= PLATFORM_FILE_ERROR_EXISTS
;
97 case ERROR_FILE_NOT_FOUND
:
98 *error
= PLATFORM_FILE_ERROR_NOT_FOUND
;
100 case ERROR_ACCESS_DENIED
:
101 *error
= PLATFORM_FILE_ERROR_ACCESS_DENIED
;
104 *error
= PLATFORM_FILE_ERROR_FAILED
;
112 bool ClosePlatformFile(PlatformFile file
) {
113 base::ThreadRestrictions::AssertIOAllowed();
114 return (CloseHandle(file
) != 0);
117 int64
SeekPlatformFile(PlatformFile file
,
118 PlatformFileWhence whence
,
120 base::ThreadRestrictions::AssertIOAllowed();
121 if (file
< 0 || offset
< 0)
124 LARGE_INTEGER distance
, res
;
125 distance
.QuadPart
= offset
;
126 DWORD move_method
= static_cast<DWORD
>(whence
);
127 if (!SetFilePointerEx(file
, distance
, &res
, move_method
))
132 int ReadPlatformFile(PlatformFile file
, int64 offset
, char* data
, int size
) {
133 base::ThreadRestrictions::AssertIOAllowed();
134 if (file
== kInvalidPlatformFileValue
)
137 LARGE_INTEGER offset_li
;
138 offset_li
.QuadPart
= offset
;
140 OVERLAPPED overlapped
= {0};
141 overlapped
.Offset
= offset_li
.LowPart
;
142 overlapped
.OffsetHigh
= offset_li
.HighPart
;
145 if (::ReadFile(file
, data
, size
, &bytes_read
, &overlapped
) != 0)
147 else if (ERROR_HANDLE_EOF
== GetLastError())
153 int ReadPlatformFileAtCurrentPos(PlatformFile file
, char* data
, int size
) {
154 return ReadPlatformFile(file
, 0, data
, size
);
157 int ReadPlatformFileNoBestEffort(PlatformFile file
, int64 offset
, char* data
,
159 return ReadPlatformFile(file
, offset
, data
, size
);
162 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file
,
163 char* data
, int size
) {
164 return ReadPlatformFile(file
, 0, data
, size
);
167 int WritePlatformFile(PlatformFile file
, int64 offset
,
168 const char* data
, int size
) {
169 base::ThreadRestrictions::AssertIOAllowed();
170 if (file
== kInvalidPlatformFileValue
)
173 LARGE_INTEGER offset_li
;
174 offset_li
.QuadPart
= offset
;
176 OVERLAPPED overlapped
= {0};
177 overlapped
.Offset
= offset_li
.LowPart
;
178 overlapped
.OffsetHigh
= offset_li
.HighPart
;
181 if (::WriteFile(file
, data
, size
, &bytes_written
, &overlapped
) != 0)
182 return bytes_written
;
187 int WritePlatformFileAtCurrentPos(PlatformFile file
, const char* data
,
189 return WritePlatformFile(file
, 0, data
, size
);
192 int WritePlatformFileCurPosNoBestEffort(PlatformFile file
,
193 const char* data
, int size
) {
194 return WritePlatformFile(file
, 0, data
, size
);
197 bool TruncatePlatformFile(PlatformFile file
, int64 length
) {
198 base::ThreadRestrictions::AssertIOAllowed();
199 if (file
== kInvalidPlatformFileValue
)
202 // Get the current file pointer.
203 LARGE_INTEGER file_pointer
;
206 if (::SetFilePointerEx(file
, zero
, &file_pointer
, FILE_CURRENT
) == 0)
209 LARGE_INTEGER length_li
;
210 length_li
.QuadPart
= length
;
211 // If length > file size, SetFilePointerEx() should extend the file
212 // with zeroes on all Windows standard file systems (NTFS, FATxx).
213 if (!::SetFilePointerEx(file
, length_li
, NULL
, FILE_BEGIN
))
216 // Set the new file length and move the file pointer to its old position.
217 // This is consistent with ftruncate()'s behavior, even when the file
218 // pointer points to a location beyond the end of the file.
219 return ((::SetEndOfFile(file
) != 0) &&
220 (::SetFilePointerEx(file
, file_pointer
, NULL
, FILE_BEGIN
) != 0));
223 bool FlushPlatformFile(PlatformFile file
) {
224 base::ThreadRestrictions::AssertIOAllowed();
225 return ((file
!= kInvalidPlatformFileValue
) && ::FlushFileBuffers(file
));
228 bool TouchPlatformFile(PlatformFile file
, const base::Time
& last_access_time
,
229 const base::Time
& last_modified_time
) {
230 base::ThreadRestrictions::AssertIOAllowed();
231 if (file
== kInvalidPlatformFileValue
)
234 FILETIME last_access_filetime
= last_access_time
.ToFileTime();
235 FILETIME last_modified_filetime
= last_modified_time
.ToFileTime();
236 return (::SetFileTime(file
, NULL
, &last_access_filetime
,
237 &last_modified_filetime
) != 0);
240 bool GetPlatformFileInfo(PlatformFile file
, PlatformFileInfo
* info
) {
241 base::ThreadRestrictions::AssertIOAllowed();
245 BY_HANDLE_FILE_INFORMATION file_info
;
246 if (GetFileInformationByHandle(file
, &file_info
) == 0)
250 size
.HighPart
= file_info
.nFileSizeHigh
;
251 size
.LowPart
= file_info
.nFileSizeLow
;
252 info
->size
= size
.QuadPart
;
254 (file_info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
255 info
->is_symbolic_link
= false; // Windows doesn't have symbolic links.
256 info
->last_modified
= base::Time::FromFileTime(file_info
.ftLastWriteTime
);
257 info
->last_accessed
= base::Time::FromFileTime(file_info
.ftLastAccessTime
);
258 info
->creation_time
= base::Time::FromFileTime(file_info
.ftCreationTime
);