1 // Copyright (c) 2011 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"
12 #include "base/eintr_wrapper.h"
13 #include "base/file_path.h"
14 #include "base/logging.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "base/utf_string_conversions.h"
18 #if defined(OS_ANDROID)
19 #include "base/os_compat_android.h"
24 #if defined(OS_BSD) || (defined(OS_MACOSX) && \
25 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
26 typedef struct stat stat_wrapper_t
;
27 static int CallFstat(int fd
, stat_wrapper_t
*sb
) {
28 base::ThreadRestrictions::AssertIOAllowed();
32 typedef struct stat64 stat_wrapper_t
;
33 static int CallFstat(int fd
, stat_wrapper_t
*sb
) {
34 base::ThreadRestrictions::AssertIOAllowed();
35 return fstat64(fd
, sb
);
39 // TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
40 PlatformFile
CreatePlatformFile(const FilePath
& name
, int flags
,
41 bool* created
, PlatformFileError
* error_code
) {
42 base::ThreadRestrictions::AssertIOAllowed();
45 if (flags
& PLATFORM_FILE_CREATE
)
46 open_flags
= O_CREAT
| O_EXCL
;
51 if (flags
& PLATFORM_FILE_CREATE_ALWAYS
) {
53 open_flags
= O_CREAT
| O_TRUNC
;
56 if (flags
& PLATFORM_FILE_OPEN_TRUNCATED
) {
58 DCHECK(flags
& PLATFORM_FILE_WRITE
);
62 if (!open_flags
&& !(flags
& PLATFORM_FILE_OPEN
) &&
63 !(flags
& PLATFORM_FILE_OPEN_ALWAYS
)) {
67 *error_code
= PLATFORM_FILE_ERROR_FAILED
;
68 return kInvalidPlatformFileValue
;
71 if (flags
& PLATFORM_FILE_WRITE
&& flags
& PLATFORM_FILE_READ
) {
73 } else if (flags
& PLATFORM_FILE_WRITE
) {
74 open_flags
|= O_WRONLY
;
75 } else if (!(flags
& PLATFORM_FILE_READ
) &&
76 !(flags
& PLATFORM_FILE_WRITE_ATTRIBUTES
) &&
77 !(flags
& PLATFORM_FILE_OPEN_ALWAYS
)) {
81 COMPILE_ASSERT(O_RDONLY
== 0, O_RDONLY_must_equal_zero
);
83 int mode
= S_IRUSR
| S_IWUSR
;
84 #if defined(OS_CHROMEOS)
85 mode
|= S_IRGRP
| S_IROTH
;
89 HANDLE_EINTR(open(name
.value().c_str(), open_flags
, mode
));
91 if (flags
& PLATFORM_FILE_OPEN_ALWAYS
) {
92 if (descriptor
<= 0) {
93 open_flags
|= O_CREAT
;
94 if (flags
& PLATFORM_FILE_EXCLUSIVE_READ
||
95 flags
& PLATFORM_FILE_EXCLUSIVE_WRITE
) {
96 open_flags
|= O_EXCL
; // together with O_CREAT implies O_NOFOLLOW
98 descriptor
= HANDLE_EINTR(
99 open(name
.value().c_str(), open_flags
, mode
));
100 if (created
&& descriptor
> 0)
105 if (created
&& (descriptor
> 0) &&
106 (flags
& (PLATFORM_FILE_CREATE_ALWAYS
| PLATFORM_FILE_CREATE
)))
109 if ((descriptor
> 0) && (flags
& PLATFORM_FILE_DELETE_ON_CLOSE
)) {
110 unlink(name
.value().c_str());
115 *error_code
= PLATFORM_FILE_OK
;
122 *error_code
= PLATFORM_FILE_ERROR_ACCESS_DENIED
;
125 *error_code
= PLATFORM_FILE_ERROR_IN_USE
;
128 *error_code
= PLATFORM_FILE_ERROR_EXISTS
;
131 *error_code
= PLATFORM_FILE_ERROR_NOT_FOUND
;
134 *error_code
= PLATFORM_FILE_ERROR_TOO_MANY_OPENED
;
137 *error_code
= PLATFORM_FILE_ERROR_NO_MEMORY
;
140 *error_code
= PLATFORM_FILE_ERROR_NO_SPACE
;
143 *error_code
= PLATFORM_FILE_ERROR_NOT_A_DIRECTORY
;
146 *error_code
= PLATFORM_FILE_ERROR_FAILED
;
154 bool ClosePlatformFile(PlatformFile file
) {
155 base::ThreadRestrictions::AssertIOAllowed();
156 return !HANDLE_EINTR(close(file
));
159 int ReadPlatformFile(PlatformFile file
, int64 offset
, char* data
, int size
) {
160 base::ThreadRestrictions::AssertIOAllowed();
161 if (file
< 0 || size
< 0)
167 rv
= HANDLE_EINTR(pread(file
, data
+ bytes_read
,
168 size
- bytes_read
, offset
+ bytes_read
));
173 } while (bytes_read
< size
);
175 return bytes_read
? bytes_read
: rv
;
178 int ReadPlatformFileNoBestEffort(PlatformFile file
, int64 offset
,
179 char* data
, int size
) {
180 base::ThreadRestrictions::AssertIOAllowed();
184 return HANDLE_EINTR(pread(file
, data
, size
, offset
));
187 int WritePlatformFile(PlatformFile file
, int64 offset
,
188 const char* data
, int size
) {
189 base::ThreadRestrictions::AssertIOAllowed();
190 if (file
< 0 || size
< 0)
193 int bytes_written
= 0;
196 rv
= HANDLE_EINTR(pwrite(file
, data
+ bytes_written
,
197 size
- bytes_written
, offset
+ bytes_written
));
202 } while (bytes_written
< size
);
204 return bytes_written
? bytes_written
: rv
;
207 bool TruncatePlatformFile(PlatformFile file
, int64 length
) {
208 base::ThreadRestrictions::AssertIOAllowed();
209 return ((file
>= 0) && !HANDLE_EINTR(ftruncate(file
, length
)));
212 bool FlushPlatformFile(PlatformFile file
) {
213 base::ThreadRestrictions::AssertIOAllowed();
214 return !HANDLE_EINTR(fsync(file
));
217 bool TouchPlatformFile(PlatformFile file
, const base::Time
& last_access_time
,
218 const base::Time
& last_modified_time
) {
219 base::ThreadRestrictions::AssertIOAllowed();
224 times
[0] = last_access_time
.ToTimeVal();
225 times
[1] = last_modified_time
.ToTimeVal();
226 return !futimes(file
, times
);
229 bool GetPlatformFileInfo(PlatformFile file
, PlatformFileInfo
* info
) {
233 stat_wrapper_t file_info
;
234 if (CallFstat(file
, &file_info
))
237 info
->is_directory
= S_ISDIR(file_info
.st_mode
);
238 info
->is_symbolic_link
= S_ISLNK(file_info
.st_mode
);
239 info
->size
= file_info
.st_size
;
240 info
->last_modified
= base::Time::FromTimeT(file_info
.st_mtime
);
241 info
->last_accessed
= base::Time::FromTimeT(file_info
.st_atime
);
242 info
->creation_time
= base::Time::FromTimeT(file_info
.st_ctime
);