Define DevTools content API
[chromium-blink-merge.git] / base / platform_file_posix.cc
blob1f50cfe06208aa1b16317a6792cfaf8513a6e7c1
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"
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <sys/stat.h>
10 #include <unistd.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"
20 #endif
22 namespace base {
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();
29 return fstat(fd, sb);
31 #else
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);
37 #endif
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();
44 int open_flags = 0;
45 if (flags & PLATFORM_FILE_CREATE)
46 open_flags = O_CREAT | O_EXCL;
48 if (created)
49 *created = false;
51 if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
52 DCHECK(!open_flags);
53 open_flags = O_CREAT | O_TRUNC;
56 if (flags & PLATFORM_FILE_OPEN_TRUNCATED) {
57 DCHECK(!open_flags);
58 DCHECK(flags & PLATFORM_FILE_WRITE);
59 open_flags = O_TRUNC;
62 if (!open_flags && !(flags & PLATFORM_FILE_OPEN) &&
63 !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
64 NOTREACHED();
65 errno = EOPNOTSUPP;
66 if (error_code)
67 *error_code = PLATFORM_FILE_ERROR_FAILED;
68 return kInvalidPlatformFileValue;
71 if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) {
72 open_flags |= O_RDWR;
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)) {
78 NOTREACHED();
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;
86 #endif
88 int descriptor =
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)
101 *created = true;
105 if (created && (descriptor > 0) &&
106 (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)))
107 *created = true;
109 if ((descriptor > 0) && (flags & PLATFORM_FILE_DELETE_ON_CLOSE)) {
110 unlink(name.value().c_str());
113 if (error_code) {
114 if (descriptor >= 0)
115 *error_code = PLATFORM_FILE_OK;
116 else {
117 switch (errno) {
118 case EACCES:
119 case EISDIR:
120 case EROFS:
121 case EPERM:
122 *error_code = PLATFORM_FILE_ERROR_ACCESS_DENIED;
123 break;
124 case ETXTBSY:
125 *error_code = PLATFORM_FILE_ERROR_IN_USE;
126 break;
127 case EEXIST:
128 *error_code = PLATFORM_FILE_ERROR_EXISTS;
129 break;
130 case ENOENT:
131 *error_code = PLATFORM_FILE_ERROR_NOT_FOUND;
132 break;
133 case EMFILE:
134 *error_code = PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
135 break;
136 case ENOMEM:
137 *error_code = PLATFORM_FILE_ERROR_NO_MEMORY;
138 break;
139 case ENOSPC:
140 *error_code = PLATFORM_FILE_ERROR_NO_SPACE;
141 break;
142 case ENOTDIR:
143 *error_code = PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
144 break;
145 default:
146 *error_code = PLATFORM_FILE_ERROR_FAILED;
151 return descriptor;
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)
162 return -1;
164 int bytes_read = 0;
165 int rv;
166 do {
167 rv = HANDLE_EINTR(pread(file, data + bytes_read,
168 size - bytes_read, offset + bytes_read));
169 if (rv <= 0)
170 break;
172 bytes_read += rv;
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();
181 if (file < 0)
182 return -1;
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)
191 return -1;
193 int bytes_written = 0;
194 int rv;
195 do {
196 rv = HANDLE_EINTR(pwrite(file, data + bytes_written,
197 size - bytes_written, offset + bytes_written));
198 if (rv <= 0)
199 break;
201 bytes_written += rv;
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();
220 if (file < 0)
221 return false;
223 timeval times[2];
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) {
230 if (!info)
231 return false;
233 stat_wrapper_t file_info;
234 if (CallFstat(file, &file_info))
235 return false;
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);
243 return true;
246 } // namespace base