Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: base/files/file_posix.cc

Issue 1124763003: Update from https://crrev.com/327068 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: update nacl, buildtools, fix display_change_notifier_unittest Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/file.h" 5 #include "base/files/file.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/files/file_posix_hooks_internal.h"
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #include "base/metrics/sparse_histogram.h" 14 #include "base/metrics/sparse_histogram.h"
16 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
17 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
19 18
20 #if defined(OS_ANDROID) 19 #if defined(OS_ANDROID)
21 #include "base/os_compat_android.h" 20 #include "base/os_compat_android.h"
22 #endif 21 #endif
23 22
24 namespace base { 23 namespace base {
25 24
26 // Make sure our Whence mappings match the system headers. 25 // Make sure our Whence mappings match the system headers.
27 COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET && 26 COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET &&
28 File::FROM_CURRENT == SEEK_CUR && 27 File::FROM_CURRENT == SEEK_CUR &&
29 File::FROM_END == SEEK_END, whence_matches_system); 28 File::FROM_END == SEEK_END, whence_matches_system);
30 29
31 namespace { 30 namespace {
32 31
33 #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) 32 #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
34 static int CallFstat(int fd, stat_wrapper_t *sb) { 33 static int CallFstat(int fd, stat_wrapper_t *sb) {
35 base::ThreadRestrictions::AssertIOAllowed(); 34 ThreadRestrictions::AssertIOAllowed();
36 return fstat(fd, sb); 35 return fstat(fd, sb);
37 } 36 }
38 #else 37 #else
39 static int CallFstat(int fd, stat_wrapper_t *sb) { 38 static int CallFstat(int fd, stat_wrapper_t *sb) {
40 base::ThreadRestrictions::AssertIOAllowed(); 39 ThreadRestrictions::AssertIOAllowed();
41 return fstat64(fd, sb); 40 return fstat64(fd, sb);
42 } 41 }
43 #endif 42 #endif
44 43
45 // NaCl doesn't provide the following system calls, so either simulate them or 44 // NaCl doesn't provide the following system calls, so either simulate them or
46 // wrap them in order to minimize the number of #ifdef's in this file. 45 // wrap them in order to minimize the number of #ifdef's in this file.
47 #if !defined(OS_NACL) 46 #if !defined(OS_NACL)
48 static bool IsOpenAppend(PlatformFile file) { 47 static bool IsOpenAppend(PlatformFile file) {
49 return (fcntl(file, F_GETFL) & O_APPEND) != 0; 48 return (fcntl(file, F_GETFL) & O_APPEND) != 0;
50 } 49 }
51 50
52 static int CallFtruncate(PlatformFile file, int64 length) { 51 static int CallFtruncate(PlatformFile file, int64 length) {
53 return HANDLE_EINTR(ftruncate(file, length)); 52 return HANDLE_EINTR(ftruncate(file, length));
54 } 53 }
55 54
56 static int CallFsync(PlatformFile file) {
57 return HANDLE_EINTR(fsync(file));
58 }
59
60 static int CallFutimes(PlatformFile file, const struct timeval times[2]) { 55 static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
61 #ifdef __USE_XOPEN2K8 56 #ifdef __USE_XOPEN2K8
62 // futimens should be available, but futimes might not be 57 // futimens should be available, but futimes might not be
63 // http://pubs.opengroup.org/onlinepubs/9699919799/ 58 // http://pubs.opengroup.org/onlinepubs/9699919799/
64 59
65 timespec ts_times[2]; 60 timespec ts_times[2];
66 ts_times[0].tv_sec = times[0].tv_sec; 61 ts_times[0].tv_sec = times[0].tv_sec;
67 ts_times[0].tv_nsec = times[0].tv_usec * 1000; 62 ts_times[0].tv_nsec = times[0].tv_usec * 1000;
68 ts_times[1].tv_sec = times[1].tv_sec; 63 ts_times[1].tv_sec = times[1].tv_sec;
69 ts_times[1].tv_nsec = times[1].tv_usec * 1000; 64 ts_times[1].tv_nsec = times[1].tv_usec * 1000;
(...skipping 21 matching lines...) Expand all
91 // standard and always appends if the file is opened with O_APPEND, just 86 // standard and always appends if the file is opened with O_APPEND, just
92 // return false here. 87 // return false here.
93 return false; 88 return false;
94 } 89 }
95 90
96 static int CallFtruncate(PlatformFile file, int64 length) { 91 static int CallFtruncate(PlatformFile file, int64 length) {
97 NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate. 92 NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate.
98 return 0; 93 return 0;
99 } 94 }
100 95
101 static int CallFsync(PlatformFile file) {
102 NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
103 return 0;
104 }
105
106 static int CallFutimes(PlatformFile file, const struct timeval times[2]) { 96 static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
107 NOTIMPLEMENTED(); // NaCl doesn't implement futimes. 97 NOTIMPLEMENTED(); // NaCl doesn't implement futimes.
108 return 0; 98 return 0;
109 } 99 }
110 100
111 static File::Error CallFctnlFlock(PlatformFile file, bool do_lock) { 101 static File::Error CallFctnlFlock(PlatformFile file, bool do_lock) {
112 NOTIMPLEMENTED(); // NaCl doesn't implement flock struct. 102 NOTIMPLEMENTED(); // NaCl doesn't implement flock struct.
113 return File::FILE_ERROR_INVALID_OPERATION; 103 return File::FILE_ERROR_INVALID_OPERATION;
114 } 104 }
115 #endif // defined(OS_NACL) 105 #endif // defined(OS_NACL)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 Time::FromTimeT(last_accessed_sec) + 150 Time::FromTimeT(last_accessed_sec) +
161 TimeDelta::FromMicroseconds(last_accessed_nsec / 151 TimeDelta::FromMicroseconds(last_accessed_nsec /
162 Time::kNanosecondsPerMicrosecond); 152 Time::kNanosecondsPerMicrosecond);
163 153
164 creation_time = 154 creation_time =
165 Time::FromTimeT(creation_time_sec) + 155 Time::FromTimeT(creation_time_sec) +
166 TimeDelta::FromMicroseconds(creation_time_nsec / 156 TimeDelta::FromMicroseconds(creation_time_nsec /
167 Time::kNanosecondsPerMicrosecond); 157 Time::kNanosecondsPerMicrosecond);
168 } 158 }
169 159
170 // Default implementations of Protect/Unprotect hooks defined as weak symbols
171 // where possible.
172 void ProtectFileDescriptor(int fd) {
173 }
174
175 void UnprotectFileDescriptor(int fd) {
176 }
177
178 // NaCl doesn't implement system calls to open files directly.
179 #if !defined(OS_NACL)
180 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
181 void File::InitializeUnsafe(const FilePath& name, uint32 flags) {
182 base::ThreadRestrictions::AssertIOAllowed();
183 DCHECK(!IsValid());
184
185 int open_flags = 0;
186 if (flags & FLAG_CREATE)
187 open_flags = O_CREAT | O_EXCL;
188
189 created_ = false;
190
191 if (flags & FLAG_CREATE_ALWAYS) {
192 DCHECK(!open_flags);
193 DCHECK(flags & FLAG_WRITE);
194 open_flags = O_CREAT | O_TRUNC;
195 }
196
197 if (flags & FLAG_OPEN_TRUNCATED) {
198 DCHECK(!open_flags);
199 DCHECK(flags & FLAG_WRITE);
200 open_flags = O_TRUNC;
201 }
202
203 if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
204 NOTREACHED();
205 errno = EOPNOTSUPP;
206 error_details_ = FILE_ERROR_FAILED;
207 return;
208 }
209
210 if (flags & FLAG_WRITE && flags & FLAG_READ) {
211 open_flags |= O_RDWR;
212 } else if (flags & FLAG_WRITE) {
213 open_flags |= O_WRONLY;
214 } else if (!(flags & FLAG_READ) &&
215 !(flags & FLAG_WRITE_ATTRIBUTES) &&
216 !(flags & FLAG_APPEND) &&
217 !(flags & FLAG_OPEN_ALWAYS)) {
218 NOTREACHED();
219 }
220
221 if (flags & FLAG_TERMINAL_DEVICE)
222 open_flags |= O_NOCTTY | O_NDELAY;
223
224 if (flags & FLAG_APPEND && flags & FLAG_READ)
225 open_flags |= O_APPEND | O_RDWR;
226 else if (flags & FLAG_APPEND)
227 open_flags |= O_APPEND | O_WRONLY;
228
229 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
230
231 int mode = S_IRUSR | S_IWUSR;
232 #if defined(OS_CHROMEOS)
233 mode |= S_IRGRP | S_IROTH;
234 #endif
235
236 int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
237
238 if (flags & FLAG_OPEN_ALWAYS) {
239 if (descriptor < 0) {
240 open_flags |= O_CREAT;
241 if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
242 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
243
244 descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
245 if (descriptor >= 0)
246 created_ = true;
247 }
248 }
249
250 if (descriptor < 0) {
251 error_details_ = File::OSErrorToFileError(errno);
252 return;
253 }
254
255 if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
256 created_ = true;
257
258 if (flags & FLAG_DELETE_ON_CLOSE)
259 unlink(name.value().c_str());
260
261 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
262 error_details_ = FILE_OK;
263 file_.reset(descriptor);
264 ProtectFileDescriptor(descriptor);
265 }
266 #endif // !defined(OS_NACL)
267
268 bool File::IsValid() const { 160 bool File::IsValid() const {
269 return file_.is_valid(); 161 return file_.is_valid();
270 } 162 }
271 163
272 PlatformFile File::GetPlatformFile() const { 164 PlatformFile File::GetPlatformFile() const {
273 return file_.get(); 165 return file_.get();
274 } 166 }
275 167
276 PlatformFile File::TakePlatformFile() { 168 PlatformFile File::TakePlatformFile() {
277 if (IsValid())
278 UnprotectFileDescriptor(GetPlatformFile());
279 return file_.release(); 169 return file_.release();
280 } 170 }
281 171
282 void File::Close() { 172 void File::Close() {
283 if (!IsValid()) 173 if (!IsValid())
284 return; 174 return;
285 175
286 base::ThreadRestrictions::AssertIOAllowed(); 176 ThreadRestrictions::AssertIOAllowed();
287 UnprotectFileDescriptor(GetPlatformFile());
288 file_.reset(); 177 file_.reset();
289 } 178 }
290 179
291 int64 File::Seek(Whence whence, int64 offset) { 180 int64 File::Seek(Whence whence, int64 offset) {
292 base::ThreadRestrictions::AssertIOAllowed(); 181 ThreadRestrictions::AssertIOAllowed();
293 DCHECK(IsValid()); 182 DCHECK(IsValid());
294 183
295 #if defined(OS_ANDROID) 184 #if defined(OS_ANDROID)
296 COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit); 185 COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit);
297 return lseek64(file_.get(), static_cast<off64_t>(offset), 186 return lseek64(file_.get(), static_cast<off64_t>(offset),
298 static_cast<int>(whence)); 187 static_cast<int>(whence));
299 #else 188 #else
300 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); 189 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit);
301 return lseek(file_.get(), static_cast<off_t>(offset), 190 return lseek(file_.get(), static_cast<off_t>(offset),
302 static_cast<int>(whence)); 191 static_cast<int>(whence));
303 #endif 192 #endif
304 } 193 }
305 194
306 int File::Read(int64 offset, char* data, int size) { 195 int File::Read(int64 offset, char* data, int size) {
307 base::ThreadRestrictions::AssertIOAllowed(); 196 ThreadRestrictions::AssertIOAllowed();
308 DCHECK(IsValid()); 197 DCHECK(IsValid());
309 if (size < 0) 198 if (size < 0)
310 return -1; 199 return -1;
311 200
312 int bytes_read = 0; 201 int bytes_read = 0;
313 int rv; 202 int rv;
314 do { 203 do {
315 rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read, 204 rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read,
316 size - bytes_read, offset + bytes_read)); 205 size - bytes_read, offset + bytes_read));
317 if (rv <= 0) 206 if (rv <= 0)
318 break; 207 break;
319 208
320 bytes_read += rv; 209 bytes_read += rv;
321 } while (bytes_read < size); 210 } while (bytes_read < size);
322 211
323 return bytes_read ? bytes_read : rv; 212 return bytes_read ? bytes_read : rv;
324 } 213 }
325 214
326 int File::ReadAtCurrentPos(char* data, int size) { 215 int File::ReadAtCurrentPos(char* data, int size) {
327 base::ThreadRestrictions::AssertIOAllowed(); 216 ThreadRestrictions::AssertIOAllowed();
328 DCHECK(IsValid()); 217 DCHECK(IsValid());
329 if (size < 0) 218 if (size < 0)
330 return -1; 219 return -1;
331 220
332 int bytes_read = 0; 221 int bytes_read = 0;
333 int rv; 222 int rv;
334 do { 223 do {
335 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read)); 224 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read));
336 if (rv <= 0) 225 if (rv <= 0)
337 break; 226 break;
338 227
339 bytes_read += rv; 228 bytes_read += rv;
340 } while (bytes_read < size); 229 } while (bytes_read < size);
341 230
342 return bytes_read ? bytes_read : rv; 231 return bytes_read ? bytes_read : rv;
343 } 232 }
344 233
345 int File::ReadNoBestEffort(int64 offset, char* data, int size) { 234 int File::ReadNoBestEffort(int64 offset, char* data, int size) {
346 base::ThreadRestrictions::AssertIOAllowed(); 235 ThreadRestrictions::AssertIOAllowed();
347 DCHECK(IsValid()); 236 DCHECK(IsValid());
348 237
349 return HANDLE_EINTR(pread(file_.get(), data, size, offset)); 238 return HANDLE_EINTR(pread(file_.get(), data, size, offset));
350 } 239 }
351 240
352 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { 241 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
353 base::ThreadRestrictions::AssertIOAllowed(); 242 ThreadRestrictions::AssertIOAllowed();
354 DCHECK(IsValid()); 243 DCHECK(IsValid());
355 if (size < 0) 244 if (size < 0)
356 return -1; 245 return -1;
357 246
358 return HANDLE_EINTR(read(file_.get(), data, size)); 247 return HANDLE_EINTR(read(file_.get(), data, size));
359 } 248 }
360 249
361 int File::Write(int64 offset, const char* data, int size) { 250 int File::Write(int64 offset, const char* data, int size) {
362 base::ThreadRestrictions::AssertIOAllowed(); 251 ThreadRestrictions::AssertIOAllowed();
363 252
364 if (IsOpenAppend(file_.get())) 253 if (IsOpenAppend(file_.get()))
365 return WriteAtCurrentPos(data, size); 254 return WriteAtCurrentPos(data, size);
366 255
367 DCHECK(IsValid()); 256 DCHECK(IsValid());
368 if (size < 0) 257 if (size < 0)
369 return -1; 258 return -1;
370 259
371 int bytes_written = 0; 260 int bytes_written = 0;
372 int rv; 261 int rv;
373 do { 262 do {
374 rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written, 263 rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written,
375 size - bytes_written, offset + bytes_written)); 264 size - bytes_written, offset + bytes_written));
376 if (rv <= 0) 265 if (rv <= 0)
377 break; 266 break;
378 267
379 bytes_written += rv; 268 bytes_written += rv;
380 } while (bytes_written < size); 269 } while (bytes_written < size);
381 270
382 return bytes_written ? bytes_written : rv; 271 return bytes_written ? bytes_written : rv;
383 } 272 }
384 273
385 int File::WriteAtCurrentPos(const char* data, int size) { 274 int File::WriteAtCurrentPos(const char* data, int size) {
386 base::ThreadRestrictions::AssertIOAllowed(); 275 ThreadRestrictions::AssertIOAllowed();
387 DCHECK(IsValid()); 276 DCHECK(IsValid());
388 if (size < 0) 277 if (size < 0)
389 return -1; 278 return -1;
390 279
391 int bytes_written = 0; 280 int bytes_written = 0;
392 int rv; 281 int rv;
393 do { 282 do {
394 rv = HANDLE_EINTR(write(file_.get(), data + bytes_written, 283 rv = HANDLE_EINTR(write(file_.get(), data + bytes_written,
395 size - bytes_written)); 284 size - bytes_written));
396 if (rv <= 0) 285 if (rv <= 0)
397 break; 286 break;
398 287
399 bytes_written += rv; 288 bytes_written += rv;
400 } while (bytes_written < size); 289 } while (bytes_written < size);
401 290
402 return bytes_written ? bytes_written : rv; 291 return bytes_written ? bytes_written : rv;
403 } 292 }
404 293
405 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { 294 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
406 base::ThreadRestrictions::AssertIOAllowed(); 295 ThreadRestrictions::AssertIOAllowed();
407 DCHECK(IsValid()); 296 DCHECK(IsValid());
408 if (size < 0) 297 if (size < 0)
409 return -1; 298 return -1;
410 299
411 return HANDLE_EINTR(write(file_.get(), data, size)); 300 return HANDLE_EINTR(write(file_.get(), data, size));
412 } 301 }
413 302
414 int64 File::GetLength() { 303 int64 File::GetLength() {
415 DCHECK(IsValid()); 304 DCHECK(IsValid());
416 305
417 stat_wrapper_t file_info; 306 stat_wrapper_t file_info;
418 if (CallFstat(file_.get(), &file_info)) 307 if (CallFstat(file_.get(), &file_info))
419 return false; 308 return false;
420 309
421 return file_info.st_size; 310 return file_info.st_size;
422 } 311 }
423 312
424 bool File::SetLength(int64 length) { 313 bool File::SetLength(int64 length) {
425 base::ThreadRestrictions::AssertIOAllowed(); 314 ThreadRestrictions::AssertIOAllowed();
426 DCHECK(IsValid()); 315 DCHECK(IsValid());
427 return !CallFtruncate(file_.get(), length); 316 return !CallFtruncate(file_.get(), length);
428 } 317 }
429 318
430 bool File::Flush() {
431 base::ThreadRestrictions::AssertIOAllowed();
432 DCHECK(IsValid());
433 return !CallFsync(file_.get());
434 }
435
436 bool File::SetTimes(Time last_access_time, Time last_modified_time) { 319 bool File::SetTimes(Time last_access_time, Time last_modified_time) {
437 base::ThreadRestrictions::AssertIOAllowed(); 320 ThreadRestrictions::AssertIOAllowed();
438 DCHECK(IsValid()); 321 DCHECK(IsValid());
439 322
440 timeval times[2]; 323 timeval times[2];
441 times[0] = last_access_time.ToTimeVal(); 324 times[0] = last_access_time.ToTimeVal();
442 times[1] = last_modified_time.ToTimeVal(); 325 times[1] = last_modified_time.ToTimeVal();
443 326
444 return !CallFutimes(file_.get(), times); 327 return !CallFutimes(file_.get(), times);
445 } 328 }
446 329
447 bool File::GetInfo(Info* info) { 330 bool File::GetInfo(Info* info) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 void File::MemoryCheckingScopedFD::Check() const { 432 void File::MemoryCheckingScopedFD::Check() const {
550 unsigned int computed_checksum; 433 unsigned int computed_checksum;
551 ComputeMemoryChecksum(&computed_checksum); 434 ComputeMemoryChecksum(&computed_checksum);
552 CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory"; 435 CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory";
553 } 436 }
554 437
555 void File::MemoryCheckingScopedFD::UpdateChecksum() { 438 void File::MemoryCheckingScopedFD::UpdateChecksum() {
556 ComputeMemoryChecksum(&file_memory_checksum_); 439 ComputeMemoryChecksum(&file_memory_checksum_);
557 } 440 }
558 441
442 // NaCl doesn't implement system calls to open files directly.
443 #if !defined(OS_NACL)
444 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
445 void File::DoInitialize(const FilePath& name, uint32 flags) {
446 ThreadRestrictions::AssertIOAllowed();
447 DCHECK(!IsValid());
448
449 int open_flags = 0;
450 if (flags & FLAG_CREATE)
451 open_flags = O_CREAT | O_EXCL;
452
453 created_ = false;
454
455 if (flags & FLAG_CREATE_ALWAYS) {
456 DCHECK(!open_flags);
457 DCHECK(flags & FLAG_WRITE);
458 open_flags = O_CREAT | O_TRUNC;
459 }
460
461 if (flags & FLAG_OPEN_TRUNCATED) {
462 DCHECK(!open_flags);
463 DCHECK(flags & FLAG_WRITE);
464 open_flags = O_TRUNC;
465 }
466
467 if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
468 NOTREACHED();
469 errno = EOPNOTSUPP;
470 error_details_ = FILE_ERROR_FAILED;
471 return;
472 }
473
474 if (flags & FLAG_WRITE && flags & FLAG_READ) {
475 open_flags |= O_RDWR;
476 } else if (flags & FLAG_WRITE) {
477 open_flags |= O_WRONLY;
478 } else if (!(flags & FLAG_READ) &&
479 !(flags & FLAG_WRITE_ATTRIBUTES) &&
480 !(flags & FLAG_APPEND) &&
481 !(flags & FLAG_OPEN_ALWAYS)) {
482 NOTREACHED();
483 }
484
485 if (flags & FLAG_TERMINAL_DEVICE)
486 open_flags |= O_NOCTTY | O_NDELAY;
487
488 if (flags & FLAG_APPEND && flags & FLAG_READ)
489 open_flags |= O_APPEND | O_RDWR;
490 else if (flags & FLAG_APPEND)
491 open_flags |= O_APPEND | O_WRONLY;
492
493 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
494
495 int mode = S_IRUSR | S_IWUSR;
496 #if defined(OS_CHROMEOS)
497 mode |= S_IRGRP | S_IROTH;
498 #endif
499
500 int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
501
502 if (flags & FLAG_OPEN_ALWAYS) {
503 if (descriptor < 0) {
504 open_flags |= O_CREAT;
505 if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
506 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
507
508 descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
509 if (descriptor >= 0)
510 created_ = true;
511 }
512 }
513
514 if (descriptor < 0) {
515 error_details_ = File::OSErrorToFileError(errno);
516 return;
517 }
518
519 if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
520 created_ = true;
521
522 if (flags & FLAG_DELETE_ON_CLOSE)
523 unlink(name.value().c_str());
524
525 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
526 error_details_ = FILE_OK;
527 file_.reset(descriptor);
528 }
529 #endif // !defined(OS_NACL)
530
531 bool File::DoFlush() {
532 ThreadRestrictions::AssertIOAllowed();
533 DCHECK(IsValid());
534 #if defined(OS_NACL)
535 NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
536 return true;
537 #elif defined(OS_LINUX) || defined(OS_ANDROID)
538 return !HANDLE_EINTR(fdatasync(file_.get()));
539 #else
540 return !HANDLE_EINTR(fsync(file_.get()));
541 #endif
542 }
543
559 void File::SetPlatformFile(PlatformFile file) { 544 void File::SetPlatformFile(PlatformFile file) {
560 CHECK(!file_.is_valid()); 545 DCHECK(!file_.is_valid());
561 file_.reset(file); 546 file_.reset(file);
562 if (file_.is_valid())
563 ProtectFileDescriptor(GetPlatformFile());
564 } 547 }
565 548
566 } // namespace base 549 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698