| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |