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 |