Proper positioning of new dialog style print preview.
[chromium-blink-merge.git] / base / platform_file_posix.cc
blob94184ab3e6eef16f3f5eadea4f4ecf93118e9ac4
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 <fcntl.h>
8 #include <errno.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/posix/eintr_wrapper.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 // Make sure our Whence mappings match the system headers.
25 COMPILE_ASSERT(PLATFORM_FILE_FROM_BEGIN == SEEK_SET &&
26 PLATFORM_FILE_FROM_CURRENT == SEEK_CUR &&
27 PLATFORM_FILE_FROM_END == SEEK_END, whence_matches_system);
29 #if defined(OS_BSD) || defined(OS_MACOSX)
30 typedef struct stat stat_wrapper_t;
31 static int CallFstat(int fd, stat_wrapper_t *sb) {
32 base::ThreadRestrictions::AssertIOAllowed();
33 return fstat(fd, sb);
35 #else
36 typedef struct stat64 stat_wrapper_t;
37 static int CallFstat(int fd, stat_wrapper_t *sb) {
38 base::ThreadRestrictions::AssertIOAllowed();
39 return fstat64(fd, sb);
41 #endif
43 // TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
44 PlatformFile CreatePlatformFileUnsafe(const FilePath& name,
45 int flags,
46 bool* created,
47 PlatformFileError* error) {
48 base::ThreadRestrictions::AssertIOAllowed();
50 int open_flags = 0;
51 if (flags & PLATFORM_FILE_CREATE)
52 open_flags = O_CREAT | O_EXCL;
54 if (created)
55 *created = false;
57 if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
58 DCHECK(!open_flags);
59 open_flags = O_CREAT | O_TRUNC;
62 if (flags & PLATFORM_FILE_OPEN_TRUNCATED) {
63 DCHECK(!open_flags);
64 DCHECK(flags & PLATFORM_FILE_WRITE);
65 open_flags = O_TRUNC;
68 if (!open_flags && !(flags & PLATFORM_FILE_OPEN) &&
69 !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
70 NOTREACHED();
71 errno = EOPNOTSUPP;
72 if (error)
73 *error = PLATFORM_FILE_ERROR_FAILED;
74 return kInvalidPlatformFileValue;
77 if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) {
78 open_flags |= O_RDWR;
79 } else if (flags & PLATFORM_FILE_WRITE) {
80 open_flags |= O_WRONLY;
81 } else if (!(flags & PLATFORM_FILE_READ) &&
82 !(flags & PLATFORM_FILE_WRITE_ATTRIBUTES) &&
83 !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
84 NOTREACHED();
87 if (flags & PLATFORM_FILE_TERMINAL_DEVICE)
88 open_flags |= O_NOCTTY | O_NDELAY;
90 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
92 int mode = S_IRUSR | S_IWUSR;
93 #if defined(OS_CHROMEOS)
94 mode |= S_IRGRP | S_IROTH;
95 #endif
97 int descriptor =
98 HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
100 if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
101 if (descriptor < 0) {
102 open_flags |= O_CREAT;
103 if (flags & PLATFORM_FILE_EXCLUSIVE_READ ||
104 flags & PLATFORM_FILE_EXCLUSIVE_WRITE) {
105 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
107 descriptor = HANDLE_EINTR(
108 open(name.value().c_str(), open_flags, mode));
109 if (created && descriptor >= 0)
110 *created = true;
114 if (created && (descriptor >= 0) &&
115 (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)))
116 *created = true;
118 if ((descriptor >= 0) && (flags & PLATFORM_FILE_DELETE_ON_CLOSE)) {
119 unlink(name.value().c_str());
122 if (error) {
123 if (descriptor >= 0)
124 *error = PLATFORM_FILE_OK;
125 else
126 *error = ErrnoToPlatformFileError(errno);
129 return descriptor;
132 FILE* FdopenPlatformFile(PlatformFile file, const char* mode) {
133 return fdopen(file, mode);
136 bool ClosePlatformFile(PlatformFile file) {
137 base::ThreadRestrictions::AssertIOAllowed();
138 return !HANDLE_EINTR(close(file));
141 int64 SeekPlatformFile(PlatformFile file,
142 PlatformFileWhence whence,
143 int64 offset) {
144 base::ThreadRestrictions::AssertIOAllowed();
145 if (file < 0 || offset < 0)
146 return -1;
148 return lseek(file, static_cast<off_t>(offset), static_cast<int>(whence));
151 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
152 base::ThreadRestrictions::AssertIOAllowed();
153 if (file < 0 || size < 0)
154 return -1;
156 int bytes_read = 0;
157 int rv;
158 do {
159 rv = HANDLE_EINTR(pread(file, data + bytes_read,
160 size - bytes_read, offset + bytes_read));
161 if (rv <= 0)
162 break;
164 bytes_read += rv;
165 } while (bytes_read < size);
167 return bytes_read ? bytes_read : rv;
170 int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) {
171 base::ThreadRestrictions::AssertIOAllowed();
172 if (file < 0 || size < 0)
173 return -1;
175 int bytes_read = 0;
176 int rv;
177 do {
178 rv = HANDLE_EINTR(read(file, data, size));
179 if (rv <= 0)
180 break;
182 bytes_read += rv;
183 } while (bytes_read < size);
185 return bytes_read ? bytes_read : rv;
188 int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset,
189 char* data, int size) {
190 base::ThreadRestrictions::AssertIOAllowed();
191 if (file < 0)
192 return -1;
194 return HANDLE_EINTR(pread(file, data, size, offset));
197 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file,
198 char* data, int size) {
199 base::ThreadRestrictions::AssertIOAllowed();
200 if (file < 0 || size < 0)
201 return -1;
203 return HANDLE_EINTR(read(file, data, size));
206 int WritePlatformFile(PlatformFile file, int64 offset,
207 const char* data, int size) {
208 base::ThreadRestrictions::AssertIOAllowed();
209 if (file < 0 || size < 0)
210 return -1;
212 int bytes_written = 0;
213 int rv;
214 do {
215 rv = HANDLE_EINTR(pwrite(file, data + bytes_written,
216 size - bytes_written, offset + bytes_written));
217 if (rv <= 0)
218 break;
220 bytes_written += rv;
221 } while (bytes_written < size);
223 return bytes_written ? bytes_written : rv;
226 int WritePlatformFileAtCurrentPos(PlatformFile file,
227 const char* data, int size) {
228 base::ThreadRestrictions::AssertIOAllowed();
229 if (file < 0 || size < 0)
230 return -1;
232 int bytes_written = 0;
233 int rv;
234 do {
235 rv = HANDLE_EINTR(write(file, data, size));
236 if (rv <= 0)
237 break;
239 bytes_written += rv;
240 } while (bytes_written < size);
242 return bytes_written ? bytes_written : rv;
245 int WritePlatformFileCurPosNoBestEffort(PlatformFile file,
246 const char* data, int size) {
247 base::ThreadRestrictions::AssertIOAllowed();
248 if (file < 0 || size < 0)
249 return -1;
251 return HANDLE_EINTR(write(file, data, size));
254 bool TruncatePlatformFile(PlatformFile file, int64 length) {
255 base::ThreadRestrictions::AssertIOAllowed();
256 return ((file >= 0) && !HANDLE_EINTR(ftruncate(file, length)));
259 bool FlushPlatformFile(PlatformFile file) {
260 base::ThreadRestrictions::AssertIOAllowed();
261 return !HANDLE_EINTR(fsync(file));
264 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
265 const base::Time& last_modified_time) {
266 base::ThreadRestrictions::AssertIOAllowed();
267 if (file < 0)
268 return false;
270 timeval times[2];
271 times[0] = last_access_time.ToTimeVal();
272 times[1] = last_modified_time.ToTimeVal();
274 #ifdef __USE_XOPEN2K8
275 // futimens should be available, but futimes might not be
276 // http://pubs.opengroup.org/onlinepubs/9699919799/
278 timespec ts_times[2];
279 ts_times[0].tv_sec = times[0].tv_sec;
280 ts_times[0].tv_nsec = times[0].tv_usec * 1000;
281 ts_times[1].tv_sec = times[1].tv_sec;
282 ts_times[1].tv_nsec = times[1].tv_usec * 1000;
284 return !futimens(file, ts_times);
285 #else
286 return !futimes(file, times);
287 #endif
290 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
291 if (!info)
292 return false;
294 stat_wrapper_t file_info;
295 if (CallFstat(file, &file_info))
296 return false;
298 info->is_directory = S_ISDIR(file_info.st_mode);
299 info->is_symbolic_link = S_ISLNK(file_info.st_mode);
300 info->size = file_info.st_size;
301 info->last_modified = base::Time::FromTimeT(file_info.st_mtime);
302 info->last_accessed = base::Time::FromTimeT(file_info.st_atime);
303 info->creation_time = base::Time::FromTimeT(file_info.st_ctime);
304 return true;
307 PlatformFileError ErrnoToPlatformFileError(int saved_errno) {
308 switch (saved_errno) {
309 case EACCES:
310 case EISDIR:
311 case EROFS:
312 case EPERM:
313 return PLATFORM_FILE_ERROR_ACCESS_DENIED;
314 case ETXTBSY:
315 return PLATFORM_FILE_ERROR_IN_USE;
316 case EEXIST:
317 return PLATFORM_FILE_ERROR_EXISTS;
318 case ENOENT:
319 return PLATFORM_FILE_ERROR_NOT_FOUND;
320 case EMFILE:
321 return PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
322 case ENOMEM:
323 return PLATFORM_FILE_ERROR_NO_MEMORY;
324 case ENOSPC:
325 return PLATFORM_FILE_ERROR_NO_SPACE;
326 case ENOTDIR:
327 return PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
328 default:
329 return PLATFORM_FILE_ERROR_FAILED;
333 } // namespace base