| 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 <stdint.h> |
| 9 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| 10 #include <unistd.h> | 11 #include <unistd.h> |
| 11 | 12 |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/posix/eintr_wrapper.h" | 15 #include "base/posix/eintr_wrapper.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/threading/thread_restrictions.h" | 17 #include "base/threading/thread_restrictions.h" |
| 18 #include "build/build_config.h" |
| 17 | 19 |
| 18 #if defined(OS_ANDROID) | 20 #if defined(OS_ANDROID) |
| 19 #include "base/os_compat_android.h" | 21 #include "base/os_compat_android.h" |
| 20 #endif | 22 #endif |
| 21 | 23 |
| 22 namespace base { | 24 namespace base { |
| 23 | 25 |
| 24 // Make sure our Whence mappings match the system headers. | 26 // Make sure our Whence mappings match the system headers. |
| 25 static_assert(File::FROM_BEGIN == SEEK_SET && File::FROM_CURRENT == SEEK_CUR && | 27 static_assert(File::FROM_BEGIN == SEEK_SET && File::FROM_CURRENT == SEEK_CUR && |
| 26 File::FROM_END == SEEK_END, | 28 File::FROM_END == SEEK_END, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 40 } | 42 } |
| 41 #endif | 43 #endif |
| 42 | 44 |
| 43 // NaCl doesn't provide the following system calls, so either simulate them or | 45 // NaCl doesn't provide the following system calls, so either simulate them or |
| 44 // wrap them in order to minimize the number of #ifdef's in this file. | 46 // wrap them in order to minimize the number of #ifdef's in this file. |
| 45 #if !defined(OS_NACL) | 47 #if !defined(OS_NACL) |
| 46 bool IsOpenAppend(PlatformFile file) { | 48 bool IsOpenAppend(PlatformFile file) { |
| 47 return (fcntl(file, F_GETFL) & O_APPEND) != 0; | 49 return (fcntl(file, F_GETFL) & O_APPEND) != 0; |
| 48 } | 50 } |
| 49 | 51 |
| 50 int CallFtruncate(PlatformFile file, int64 length) { | 52 int CallFtruncate(PlatformFile file, int64_t length) { |
| 51 return HANDLE_EINTR(ftruncate(file, length)); | 53 return HANDLE_EINTR(ftruncate(file, length)); |
| 52 } | 54 } |
| 53 | 55 |
| 54 int CallFutimes(PlatformFile file, const struct timeval times[2]) { | 56 int CallFutimes(PlatformFile file, const struct timeval times[2]) { |
| 55 #ifdef __USE_XOPEN2K8 | 57 #ifdef __USE_XOPEN2K8 |
| 56 // futimens should be available, but futimes might not be | 58 // futimens should be available, but futimes might not be |
| 57 // http://pubs.opengroup.org/onlinepubs/9699919799/ | 59 // http://pubs.opengroup.org/onlinepubs/9699919799/ |
| 58 | 60 |
| 59 timespec ts_times[2]; | 61 timespec ts_times[2]; |
| 60 ts_times[0].tv_sec = times[0].tv_sec; | 62 ts_times[0].tv_sec = times[0].tv_sec; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 80 } | 82 } |
| 81 #else // defined(OS_NACL) | 83 #else // defined(OS_NACL) |
| 82 | 84 |
| 83 bool IsOpenAppend(PlatformFile file) { | 85 bool IsOpenAppend(PlatformFile file) { |
| 84 // NaCl doesn't implement fcntl. Since NaCl's write conforms to the POSIX | 86 // NaCl doesn't implement fcntl. Since NaCl's write conforms to the POSIX |
| 85 // standard and always appends if the file is opened with O_APPEND, just | 87 // standard and always appends if the file is opened with O_APPEND, just |
| 86 // return false here. | 88 // return false here. |
| 87 return false; | 89 return false; |
| 88 } | 90 } |
| 89 | 91 |
| 90 int CallFtruncate(PlatformFile file, int64 length) { | 92 int CallFtruncate(PlatformFile file, int64_t length) { |
| 91 NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate. | 93 NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate. |
| 92 return 0; | 94 return 0; |
| 93 } | 95 } |
| 94 | 96 |
| 95 int CallFutimes(PlatformFile file, const struct timeval times[2]) { | 97 int CallFutimes(PlatformFile file, const struct timeval times[2]) { |
| 96 NOTIMPLEMENTED(); // NaCl doesn't implement futimes. | 98 NOTIMPLEMENTED(); // NaCl doesn't implement futimes. |
| 97 return 0; | 99 return 0; |
| 98 } | 100 } |
| 99 | 101 |
| 100 File::Error CallFcntlFlock(PlatformFile file, bool do_lock) { | 102 File::Error CallFcntlFlock(PlatformFile file, bool do_lock) { |
| 101 NOTIMPLEMENTED(); // NaCl doesn't implement flock struct. | 103 NOTIMPLEMENTED(); // NaCl doesn't implement flock struct. |
| 102 return File::FILE_ERROR_INVALID_OPERATION; | 104 return File::FILE_ERROR_INVALID_OPERATION; |
| 103 } | 105 } |
| 104 #endif // defined(OS_NACL) | 106 #endif // defined(OS_NACL) |
| 105 | 107 |
| 106 } // namespace | 108 } // namespace |
| 107 | 109 |
| 108 void File::Info::FromStat(const stat_wrapper_t& stat_info) { | 110 void File::Info::FromStat(const stat_wrapper_t& stat_info) { |
| 109 is_directory = S_ISDIR(stat_info.st_mode); | 111 is_directory = S_ISDIR(stat_info.st_mode); |
| 110 is_symbolic_link = S_ISLNK(stat_info.st_mode); | 112 is_symbolic_link = S_ISLNK(stat_info.st_mode); |
| 111 size = stat_info.st_size; | 113 size = stat_info.st_size; |
| 112 | 114 |
| 113 #if defined(OS_LINUX) | 115 #if defined(OS_LINUX) |
| 114 time_t last_modified_sec = stat_info.st_mtim.tv_sec; | 116 time_t last_modified_sec = stat_info.st_mtim.tv_sec; |
| 115 int64 last_modified_nsec = stat_info.st_mtim.tv_nsec; | 117 int64_t last_modified_nsec = stat_info.st_mtim.tv_nsec; |
| 116 time_t last_accessed_sec = stat_info.st_atim.tv_sec; | 118 time_t last_accessed_sec = stat_info.st_atim.tv_sec; |
| 117 int64 last_accessed_nsec = stat_info.st_atim.tv_nsec; | 119 int64_t last_accessed_nsec = stat_info.st_atim.tv_nsec; |
| 118 time_t creation_time_sec = stat_info.st_ctim.tv_sec; | 120 time_t creation_time_sec = stat_info.st_ctim.tv_sec; |
| 119 int64 creation_time_nsec = stat_info.st_ctim.tv_nsec; | 121 int64_t creation_time_nsec = stat_info.st_ctim.tv_nsec; |
| 120 #elif defined(OS_ANDROID) | 122 #elif defined(OS_ANDROID) |
| 121 time_t last_modified_sec = stat_info.st_mtime; | 123 time_t last_modified_sec = stat_info.st_mtime; |
| 122 int64 last_modified_nsec = stat_info.st_mtime_nsec; | 124 int64_t last_modified_nsec = stat_info.st_mtime_nsec; |
| 123 time_t last_accessed_sec = stat_info.st_atime; | 125 time_t last_accessed_sec = stat_info.st_atime; |
| 124 int64 last_accessed_nsec = stat_info.st_atime_nsec; | 126 int64_t last_accessed_nsec = stat_info.st_atime_nsec; |
| 125 time_t creation_time_sec = stat_info.st_ctime; | 127 time_t creation_time_sec = stat_info.st_ctime; |
| 126 int64 creation_time_nsec = stat_info.st_ctime_nsec; | 128 int64_t creation_time_nsec = stat_info.st_ctime_nsec; |
| 127 #elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD) | 129 #elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD) |
| 128 time_t last_modified_sec = stat_info.st_mtimespec.tv_sec; | 130 time_t last_modified_sec = stat_info.st_mtimespec.tv_sec; |
| 129 int64 last_modified_nsec = stat_info.st_mtimespec.tv_nsec; | 131 int64_t last_modified_nsec = stat_info.st_mtimespec.tv_nsec; |
| 130 time_t last_accessed_sec = stat_info.st_atimespec.tv_sec; | 132 time_t last_accessed_sec = stat_info.st_atimespec.tv_sec; |
| 131 int64 last_accessed_nsec = stat_info.st_atimespec.tv_nsec; | 133 int64_t last_accessed_nsec = stat_info.st_atimespec.tv_nsec; |
| 132 time_t creation_time_sec = stat_info.st_ctimespec.tv_sec; | 134 time_t creation_time_sec = stat_info.st_ctimespec.tv_sec; |
| 133 int64 creation_time_nsec = stat_info.st_ctimespec.tv_nsec; | 135 int64_t creation_time_nsec = stat_info.st_ctimespec.tv_nsec; |
| 134 #else | 136 #else |
| 135 time_t last_modified_sec = stat_info.st_mtime; | 137 time_t last_modified_sec = stat_info.st_mtime; |
| 136 int64 last_modified_nsec = 0; | 138 int64_t last_modified_nsec = 0; |
| 137 time_t last_accessed_sec = stat_info.st_atime; | 139 time_t last_accessed_sec = stat_info.st_atime; |
| 138 int64 last_accessed_nsec = 0; | 140 int64_t last_accessed_nsec = 0; |
| 139 time_t creation_time_sec = stat_info.st_ctime; | 141 time_t creation_time_sec = stat_info.st_ctime; |
| 140 int64 creation_time_nsec = 0; | 142 int64_t creation_time_nsec = 0; |
| 141 #endif | 143 #endif |
| 142 | 144 |
| 143 last_modified = | 145 last_modified = |
| 144 Time::FromTimeT(last_modified_sec) + | 146 Time::FromTimeT(last_modified_sec) + |
| 145 TimeDelta::FromMicroseconds(last_modified_nsec / | 147 TimeDelta::FromMicroseconds(last_modified_nsec / |
| 146 Time::kNanosecondsPerMicrosecond); | 148 Time::kNanosecondsPerMicrosecond); |
| 147 | 149 |
| 148 last_accessed = | 150 last_accessed = |
| 149 Time::FromTimeT(last_accessed_sec) + | 151 Time::FromTimeT(last_accessed_sec) + |
| 150 TimeDelta::FromMicroseconds(last_accessed_nsec / | 152 TimeDelta::FromMicroseconds(last_accessed_nsec / |
| (...skipping 19 matching lines...) Expand all Loading... |
| 170 | 172 |
| 171 void File::Close() { | 173 void File::Close() { |
| 172 if (!IsValid()) | 174 if (!IsValid()) |
| 173 return; | 175 return; |
| 174 | 176 |
| 175 SCOPED_FILE_TRACE("Close"); | 177 SCOPED_FILE_TRACE("Close"); |
| 176 ThreadRestrictions::AssertIOAllowed(); | 178 ThreadRestrictions::AssertIOAllowed(); |
| 177 file_.reset(); | 179 file_.reset(); |
| 178 } | 180 } |
| 179 | 181 |
| 180 int64 File::Seek(Whence whence, int64 offset) { | 182 int64_t File::Seek(Whence whence, int64_t offset) { |
| 181 ThreadRestrictions::AssertIOAllowed(); | 183 ThreadRestrictions::AssertIOAllowed(); |
| 182 DCHECK(IsValid()); | 184 DCHECK(IsValid()); |
| 183 | 185 |
| 184 SCOPED_FILE_TRACE_WITH_SIZE("Seek", offset); | 186 SCOPED_FILE_TRACE_WITH_SIZE("Seek", offset); |
| 185 | 187 |
| 186 #if defined(OS_ANDROID) | 188 #if defined(OS_ANDROID) |
| 187 static_assert(sizeof(int64) == sizeof(off64_t), "off64_t must be 64 bits"); | 189 static_assert(sizeof(int64_t) == sizeof(off64_t), "off64_t must be 64 bits"); |
| 188 return lseek64(file_.get(), static_cast<off64_t>(offset), | 190 return lseek64(file_.get(), static_cast<off64_t>(offset), |
| 189 static_cast<int>(whence)); | 191 static_cast<int>(whence)); |
| 190 #else | 192 #else |
| 191 static_assert(sizeof(int64) == sizeof(off_t), "off_t must be 64 bits"); | 193 static_assert(sizeof(int64_t) == sizeof(off_t), "off_t must be 64 bits"); |
| 192 return lseek(file_.get(), static_cast<off_t>(offset), | 194 return lseek(file_.get(), static_cast<off_t>(offset), |
| 193 static_cast<int>(whence)); | 195 static_cast<int>(whence)); |
| 194 #endif | 196 #endif |
| 195 } | 197 } |
| 196 | 198 |
| 197 int File::Read(int64 offset, char* data, int size) { | 199 int File::Read(int64_t offset, char* data, int size) { |
| 198 ThreadRestrictions::AssertIOAllowed(); | 200 ThreadRestrictions::AssertIOAllowed(); |
| 199 DCHECK(IsValid()); | 201 DCHECK(IsValid()); |
| 200 if (size < 0) | 202 if (size < 0) |
| 201 return -1; | 203 return -1; |
| 202 | 204 |
| 203 SCOPED_FILE_TRACE_WITH_SIZE("Read", size); | 205 SCOPED_FILE_TRACE_WITH_SIZE("Read", size); |
| 204 | 206 |
| 205 int bytes_read = 0; | 207 int bytes_read = 0; |
| 206 int rv; | 208 int rv; |
| 207 do { | 209 do { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 230 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read)); | 232 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read)); |
| 231 if (rv <= 0) | 233 if (rv <= 0) |
| 232 break; | 234 break; |
| 233 | 235 |
| 234 bytes_read += rv; | 236 bytes_read += rv; |
| 235 } while (bytes_read < size); | 237 } while (bytes_read < size); |
| 236 | 238 |
| 237 return bytes_read ? bytes_read : rv; | 239 return bytes_read ? bytes_read : rv; |
| 238 } | 240 } |
| 239 | 241 |
| 240 int File::ReadNoBestEffort(int64 offset, char* data, int size) { | 242 int File::ReadNoBestEffort(int64_t offset, char* data, int size) { |
| 241 ThreadRestrictions::AssertIOAllowed(); | 243 ThreadRestrictions::AssertIOAllowed(); |
| 242 DCHECK(IsValid()); | 244 DCHECK(IsValid()); |
| 243 SCOPED_FILE_TRACE_WITH_SIZE("ReadNoBestEffort", size); | 245 SCOPED_FILE_TRACE_WITH_SIZE("ReadNoBestEffort", size); |
| 244 return HANDLE_EINTR(pread(file_.get(), data, size, offset)); | 246 return HANDLE_EINTR(pread(file_.get(), data, size, offset)); |
| 245 } | 247 } |
| 246 | 248 |
| 247 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { | 249 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { |
| 248 ThreadRestrictions::AssertIOAllowed(); | 250 ThreadRestrictions::AssertIOAllowed(); |
| 249 DCHECK(IsValid()); | 251 DCHECK(IsValid()); |
| 250 if (size < 0) | 252 if (size < 0) |
| 251 return -1; | 253 return -1; |
| 252 | 254 |
| 253 SCOPED_FILE_TRACE_WITH_SIZE("ReadAtCurrentPosNoBestEffort", size); | 255 SCOPED_FILE_TRACE_WITH_SIZE("ReadAtCurrentPosNoBestEffort", size); |
| 254 return HANDLE_EINTR(read(file_.get(), data, size)); | 256 return HANDLE_EINTR(read(file_.get(), data, size)); |
| 255 } | 257 } |
| 256 | 258 |
| 257 int File::Write(int64 offset, const char* data, int size) { | 259 int File::Write(int64_t offset, const char* data, int size) { |
| 258 ThreadRestrictions::AssertIOAllowed(); | 260 ThreadRestrictions::AssertIOAllowed(); |
| 259 | 261 |
| 260 if (IsOpenAppend(file_.get())) | 262 if (IsOpenAppend(file_.get())) |
| 261 return WriteAtCurrentPos(data, size); | 263 return WriteAtCurrentPos(data, size); |
| 262 | 264 |
| 263 DCHECK(IsValid()); | 265 DCHECK(IsValid()); |
| 264 if (size < 0) | 266 if (size < 0) |
| 265 return -1; | 267 return -1; |
| 266 | 268 |
| 267 SCOPED_FILE_TRACE_WITH_SIZE("Write", size); | 269 SCOPED_FILE_TRACE_WITH_SIZE("Write", size); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { | 307 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { |
| 306 ThreadRestrictions::AssertIOAllowed(); | 308 ThreadRestrictions::AssertIOAllowed(); |
| 307 DCHECK(IsValid()); | 309 DCHECK(IsValid()); |
| 308 if (size < 0) | 310 if (size < 0) |
| 309 return -1; | 311 return -1; |
| 310 | 312 |
| 311 SCOPED_FILE_TRACE_WITH_SIZE("WriteAtCurrentPosNoBestEffort", size); | 313 SCOPED_FILE_TRACE_WITH_SIZE("WriteAtCurrentPosNoBestEffort", size); |
| 312 return HANDLE_EINTR(write(file_.get(), data, size)); | 314 return HANDLE_EINTR(write(file_.get(), data, size)); |
| 313 } | 315 } |
| 314 | 316 |
| 315 int64 File::GetLength() { | 317 int64_t File::GetLength() { |
| 316 DCHECK(IsValid()); | 318 DCHECK(IsValid()); |
| 317 | 319 |
| 318 SCOPED_FILE_TRACE("GetLength"); | 320 SCOPED_FILE_TRACE("GetLength"); |
| 319 | 321 |
| 320 stat_wrapper_t file_info; | 322 stat_wrapper_t file_info; |
| 321 if (CallFstat(file_.get(), &file_info)) | 323 if (CallFstat(file_.get(), &file_info)) |
| 322 return false; | 324 return false; |
| 323 | 325 |
| 324 return file_info.st_size; | 326 return file_info.st_size; |
| 325 } | 327 } |
| 326 | 328 |
| 327 bool File::SetLength(int64 length) { | 329 bool File::SetLength(int64_t length) { |
| 328 ThreadRestrictions::AssertIOAllowed(); | 330 ThreadRestrictions::AssertIOAllowed(); |
| 329 DCHECK(IsValid()); | 331 DCHECK(IsValid()); |
| 330 | 332 |
| 331 SCOPED_FILE_TRACE_WITH_SIZE("SetLength", length); | 333 SCOPED_FILE_TRACE_WITH_SIZE("SetLength", length); |
| 332 return !CallFtruncate(file_.get(), length); | 334 return !CallFtruncate(file_.get(), length); |
| 333 } | 335 } |
| 334 | 336 |
| 335 bool File::SetTimes(Time last_access_time, Time last_modified_time) { | 337 bool File::SetTimes(Time last_access_time, Time last_modified_time) { |
| 336 ThreadRestrictions::AssertIOAllowed(); | 338 ThreadRestrictions::AssertIOAllowed(); |
| 337 DCHECK(IsValid()); | 339 DCHECK(IsValid()); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Posix", | 418 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Posix", |
| 417 saved_errno); | 419 saved_errno); |
| 418 #endif | 420 #endif |
| 419 return FILE_ERROR_FAILED; | 421 return FILE_ERROR_FAILED; |
| 420 } | 422 } |
| 421 } | 423 } |
| 422 | 424 |
| 423 // NaCl doesn't implement system calls to open files directly. | 425 // NaCl doesn't implement system calls to open files directly. |
| 424 #if !defined(OS_NACL) | 426 #if !defined(OS_NACL) |
| 425 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? | 427 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? |
| 426 void File::DoInitialize(const FilePath& path, uint32 flags) { | 428 void File::DoInitialize(const FilePath& path, uint32_t flags) { |
| 427 ThreadRestrictions::AssertIOAllowed(); | 429 ThreadRestrictions::AssertIOAllowed(); |
| 428 DCHECK(!IsValid()); | 430 DCHECK(!IsValid()); |
| 429 | 431 |
| 430 int open_flags = 0; | 432 int open_flags = 0; |
| 431 if (flags & FLAG_CREATE) | 433 if (flags & FLAG_CREATE) |
| 432 open_flags = O_CREAT | O_EXCL; | 434 open_flags = O_CREAT | O_EXCL; |
| 433 | 435 |
| 434 created_ = false; | 436 created_ = false; |
| 435 | 437 |
| 436 if (flags & FLAG_CREATE_ALWAYS) { | 438 if (flags & FLAG_CREATE_ALWAYS) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 return !HANDLE_EINTR(fsync(file_.get())); | 524 return !HANDLE_EINTR(fsync(file_.get())); |
| 523 #endif | 525 #endif |
| 524 } | 526 } |
| 525 | 527 |
| 526 void File::SetPlatformFile(PlatformFile file) { | 528 void File::SetPlatformFile(PlatformFile file) { |
| 527 DCHECK(!file_.is_valid()); | 529 DCHECK(!file_.is_valid()); |
| 528 file_.reset(file); | 530 file_.reset(file); |
| 529 } | 531 } |
| 530 | 532 |
| 531 } // namespace base | 533 } // namespace base |
| OLD | NEW |