1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/files/file.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <errno.h>
8*635a8641SAndroid Build Coastguard Worker #include <fcntl.h>
9*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
10*635a8641SAndroid Build Coastguard Worker #include <sys/stat.h>
11*635a8641SAndroid Build Coastguard Worker #include <unistd.h>
12*635a8641SAndroid Build Coastguard Worker
13*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
18*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
21*635a8641SAndroid Build Coastguard Worker #include "base/os_compat_android.h"
22*635a8641SAndroid Build Coastguard Worker #endif
23*635a8641SAndroid Build Coastguard Worker
24*635a8641SAndroid Build Coastguard Worker namespace base {
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker // Make sure our Whence mappings match the system headers.
27*635a8641SAndroid Build Coastguard Worker static_assert(File::FROM_BEGIN == SEEK_SET && File::FROM_CURRENT == SEEK_CUR &&
28*635a8641SAndroid Build Coastguard Worker File::FROM_END == SEEK_END,
29*635a8641SAndroid Build Coastguard Worker "whence mapping must match the system headers");
30*635a8641SAndroid Build Coastguard Worker
31*635a8641SAndroid Build Coastguard Worker namespace {
32*635a8641SAndroid Build Coastguard Worker
33*635a8641SAndroid Build Coastguard Worker #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) || \
34*635a8641SAndroid Build Coastguard Worker defined(OS_FUCHSIA) || (defined(OS_ANDROID) && __ANDROID_API__ < 21)
CallFstat(int fd,stat_wrapper_t * sb)35*635a8641SAndroid Build Coastguard Worker int CallFstat(int fd, stat_wrapper_t *sb) {
36*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
37*635a8641SAndroid Build Coastguard Worker return fstat(fd, sb);
38*635a8641SAndroid Build Coastguard Worker }
39*635a8641SAndroid Build Coastguard Worker #else
40*635a8641SAndroid Build Coastguard Worker int CallFstat(int fd, stat_wrapper_t *sb) {
41*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
42*635a8641SAndroid Build Coastguard Worker return fstat64(fd, sb);
43*635a8641SAndroid Build Coastguard Worker }
44*635a8641SAndroid Build Coastguard Worker #endif
45*635a8641SAndroid Build Coastguard Worker
46*635a8641SAndroid Build Coastguard Worker // NaCl doesn't provide the following system calls, so either simulate them or
47*635a8641SAndroid Build Coastguard Worker // wrap them in order to minimize the number of #ifdef's in this file.
48*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL) && !defined(OS_AIX)
IsOpenAppend(PlatformFile file)49*635a8641SAndroid Build Coastguard Worker bool IsOpenAppend(PlatformFile file) {
50*635a8641SAndroid Build Coastguard Worker return (fcntl(file, F_GETFL) & O_APPEND) != 0;
51*635a8641SAndroid Build Coastguard Worker }
52*635a8641SAndroid Build Coastguard Worker
CallFtruncate(PlatformFile file,int64_t length)53*635a8641SAndroid Build Coastguard Worker int CallFtruncate(PlatformFile file, int64_t length) {
54*635a8641SAndroid Build Coastguard Worker return HANDLE_EINTR(ftruncate(file, length));
55*635a8641SAndroid Build Coastguard Worker }
56*635a8641SAndroid Build Coastguard Worker
CallFutimes(PlatformFile file,const struct timeval times[2])57*635a8641SAndroid Build Coastguard Worker int CallFutimes(PlatformFile file, const struct timeval times[2]) {
58*635a8641SAndroid Build Coastguard Worker #ifdef __USE_XOPEN2K8
59*635a8641SAndroid Build Coastguard Worker // futimens should be available, but futimes might not be
60*635a8641SAndroid Build Coastguard Worker // http://pubs.opengroup.org/onlinepubs/9699919799/
61*635a8641SAndroid Build Coastguard Worker
62*635a8641SAndroid Build Coastguard Worker timespec ts_times[2];
63*635a8641SAndroid Build Coastguard Worker ts_times[0].tv_sec = times[0].tv_sec;
64*635a8641SAndroid Build Coastguard Worker ts_times[0].tv_nsec = times[0].tv_usec * 1000;
65*635a8641SAndroid Build Coastguard Worker ts_times[1].tv_sec = times[1].tv_sec;
66*635a8641SAndroid Build Coastguard Worker ts_times[1].tv_nsec = times[1].tv_usec * 1000;
67*635a8641SAndroid Build Coastguard Worker
68*635a8641SAndroid Build Coastguard Worker return futimens(file, ts_times);
69*635a8641SAndroid Build Coastguard Worker #else
70*635a8641SAndroid Build Coastguard Worker return futimes(file, times);
71*635a8641SAndroid Build Coastguard Worker #endif
72*635a8641SAndroid Build Coastguard Worker }
73*635a8641SAndroid Build Coastguard Worker
74*635a8641SAndroid Build Coastguard Worker #if !defined(OS_FUCHSIA)
CallFcntlFlock(PlatformFile file,bool do_lock)75*635a8641SAndroid Build Coastguard Worker File::Error CallFcntlFlock(PlatformFile file, bool do_lock) {
76*635a8641SAndroid Build Coastguard Worker struct flock lock;
77*635a8641SAndroid Build Coastguard Worker lock.l_type = do_lock ? F_WRLCK : F_UNLCK;
78*635a8641SAndroid Build Coastguard Worker lock.l_whence = SEEK_SET;
79*635a8641SAndroid Build Coastguard Worker lock.l_start = 0;
80*635a8641SAndroid Build Coastguard Worker lock.l_len = 0; // Lock entire file.
81*635a8641SAndroid Build Coastguard Worker if (HANDLE_EINTR(fcntl(file, F_SETLK, &lock)) == -1)
82*635a8641SAndroid Build Coastguard Worker return File::GetLastFileError();
83*635a8641SAndroid Build Coastguard Worker return File::FILE_OK;
84*635a8641SAndroid Build Coastguard Worker }
85*635a8641SAndroid Build Coastguard Worker #endif
86*635a8641SAndroid Build Coastguard Worker
87*635a8641SAndroid Build Coastguard Worker #else // defined(OS_NACL) && !defined(OS_AIX)
88*635a8641SAndroid Build Coastguard Worker
IsOpenAppend(PlatformFile file)89*635a8641SAndroid Build Coastguard Worker bool IsOpenAppend(PlatformFile file) {
90*635a8641SAndroid Build Coastguard Worker // NaCl doesn't implement fcntl. Since NaCl's write conforms to the POSIX
91*635a8641SAndroid Build Coastguard Worker // standard and always appends if the file is opened with O_APPEND, just
92*635a8641SAndroid Build Coastguard Worker // return false here.
93*635a8641SAndroid Build Coastguard Worker return false;
94*635a8641SAndroid Build Coastguard Worker }
95*635a8641SAndroid Build Coastguard Worker
CallFtruncate(PlatformFile file,int64_t length)96*635a8641SAndroid Build Coastguard Worker int CallFtruncate(PlatformFile file, int64_t length) {
97*635a8641SAndroid Build Coastguard Worker NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate.
98*635a8641SAndroid Build Coastguard Worker return 0;
99*635a8641SAndroid Build Coastguard Worker }
100*635a8641SAndroid Build Coastguard Worker
CallFutimes(PlatformFile file,const struct timeval times[2])101*635a8641SAndroid Build Coastguard Worker int CallFutimes(PlatformFile file, const struct timeval times[2]) {
102*635a8641SAndroid Build Coastguard Worker NOTIMPLEMENTED(); // NaCl doesn't implement futimes.
103*635a8641SAndroid Build Coastguard Worker return 0;
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
CallFcntlFlock(PlatformFile file,bool do_lock)106*635a8641SAndroid Build Coastguard Worker File::Error CallFcntlFlock(PlatformFile file, bool do_lock) {
107*635a8641SAndroid Build Coastguard Worker NOTIMPLEMENTED(); // NaCl doesn't implement flock struct.
108*635a8641SAndroid Build Coastguard Worker return File::FILE_ERROR_INVALID_OPERATION;
109*635a8641SAndroid Build Coastguard Worker }
110*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_NACL)
111*635a8641SAndroid Build Coastguard Worker
112*635a8641SAndroid Build Coastguard Worker } // namespace
113*635a8641SAndroid Build Coastguard Worker
FromStat(const stat_wrapper_t & stat_info)114*635a8641SAndroid Build Coastguard Worker void File::Info::FromStat(const stat_wrapper_t& stat_info) {
115*635a8641SAndroid Build Coastguard Worker is_directory = S_ISDIR(stat_info.st_mode);
116*635a8641SAndroid Build Coastguard Worker is_symbolic_link = S_ISLNK(stat_info.st_mode);
117*635a8641SAndroid Build Coastguard Worker size = stat_info.st_size;
118*635a8641SAndroid Build Coastguard Worker
119*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX)
120*635a8641SAndroid Build Coastguard Worker time_t last_modified_sec = stat_info.st_mtim.tv_sec;
121*635a8641SAndroid Build Coastguard Worker int64_t last_modified_nsec = stat_info.st_mtim.tv_nsec;
122*635a8641SAndroid Build Coastguard Worker time_t last_accessed_sec = stat_info.st_atim.tv_sec;
123*635a8641SAndroid Build Coastguard Worker int64_t last_accessed_nsec = stat_info.st_atim.tv_nsec;
124*635a8641SAndroid Build Coastguard Worker time_t creation_time_sec = stat_info.st_ctim.tv_sec;
125*635a8641SAndroid Build Coastguard Worker int64_t creation_time_nsec = stat_info.st_ctim.tv_nsec;
126*635a8641SAndroid Build Coastguard Worker #elif defined(OS_ANDROID)
127*635a8641SAndroid Build Coastguard Worker time_t last_modified_sec = stat_info.st_mtime;
128*635a8641SAndroid Build Coastguard Worker int64_t last_modified_nsec = stat_info.st_mtime_nsec;
129*635a8641SAndroid Build Coastguard Worker time_t last_accessed_sec = stat_info.st_atime;
130*635a8641SAndroid Build Coastguard Worker int64_t last_accessed_nsec = stat_info.st_atime_nsec;
131*635a8641SAndroid Build Coastguard Worker time_t creation_time_sec = stat_info.st_ctime;
132*635a8641SAndroid Build Coastguard Worker int64_t creation_time_nsec = stat_info.st_ctime_nsec;
133*635a8641SAndroid Build Coastguard Worker #elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD)
134*635a8641SAndroid Build Coastguard Worker time_t last_modified_sec = stat_info.st_mtimespec.tv_sec;
135*635a8641SAndroid Build Coastguard Worker int64_t last_modified_nsec = stat_info.st_mtimespec.tv_nsec;
136*635a8641SAndroid Build Coastguard Worker time_t last_accessed_sec = stat_info.st_atimespec.tv_sec;
137*635a8641SAndroid Build Coastguard Worker int64_t last_accessed_nsec = stat_info.st_atimespec.tv_nsec;
138*635a8641SAndroid Build Coastguard Worker time_t creation_time_sec = stat_info.st_ctimespec.tv_sec;
139*635a8641SAndroid Build Coastguard Worker int64_t creation_time_nsec = stat_info.st_ctimespec.tv_nsec;
140*635a8641SAndroid Build Coastguard Worker #else
141*635a8641SAndroid Build Coastguard Worker time_t last_modified_sec = stat_info.st_mtime;
142*635a8641SAndroid Build Coastguard Worker int64_t last_modified_nsec = 0;
143*635a8641SAndroid Build Coastguard Worker time_t last_accessed_sec = stat_info.st_atime;
144*635a8641SAndroid Build Coastguard Worker int64_t last_accessed_nsec = 0;
145*635a8641SAndroid Build Coastguard Worker time_t creation_time_sec = stat_info.st_ctime;
146*635a8641SAndroid Build Coastguard Worker int64_t creation_time_nsec = 0;
147*635a8641SAndroid Build Coastguard Worker #endif
148*635a8641SAndroid Build Coastguard Worker
149*635a8641SAndroid Build Coastguard Worker last_modified =
150*635a8641SAndroid Build Coastguard Worker Time::FromTimeT(last_modified_sec) +
151*635a8641SAndroid Build Coastguard Worker TimeDelta::FromMicroseconds(last_modified_nsec /
152*635a8641SAndroid Build Coastguard Worker Time::kNanosecondsPerMicrosecond);
153*635a8641SAndroid Build Coastguard Worker
154*635a8641SAndroid Build Coastguard Worker last_accessed =
155*635a8641SAndroid Build Coastguard Worker Time::FromTimeT(last_accessed_sec) +
156*635a8641SAndroid Build Coastguard Worker TimeDelta::FromMicroseconds(last_accessed_nsec /
157*635a8641SAndroid Build Coastguard Worker Time::kNanosecondsPerMicrosecond);
158*635a8641SAndroid Build Coastguard Worker
159*635a8641SAndroid Build Coastguard Worker creation_time =
160*635a8641SAndroid Build Coastguard Worker Time::FromTimeT(creation_time_sec) +
161*635a8641SAndroid Build Coastguard Worker TimeDelta::FromMicroseconds(creation_time_nsec /
162*635a8641SAndroid Build Coastguard Worker Time::kNanosecondsPerMicrosecond);
163*635a8641SAndroid Build Coastguard Worker }
164*635a8641SAndroid Build Coastguard Worker
IsValid() const165*635a8641SAndroid Build Coastguard Worker bool File::IsValid() const {
166*635a8641SAndroid Build Coastguard Worker return file_.is_valid();
167*635a8641SAndroid Build Coastguard Worker }
168*635a8641SAndroid Build Coastguard Worker
GetPlatformFile() const169*635a8641SAndroid Build Coastguard Worker PlatformFile File::GetPlatformFile() const {
170*635a8641SAndroid Build Coastguard Worker return file_.get();
171*635a8641SAndroid Build Coastguard Worker }
172*635a8641SAndroid Build Coastguard Worker
TakePlatformFile()173*635a8641SAndroid Build Coastguard Worker PlatformFile File::TakePlatformFile() {
174*635a8641SAndroid Build Coastguard Worker return file_.release();
175*635a8641SAndroid Build Coastguard Worker }
176*635a8641SAndroid Build Coastguard Worker
Close()177*635a8641SAndroid Build Coastguard Worker void File::Close() {
178*635a8641SAndroid Build Coastguard Worker if (!IsValid())
179*635a8641SAndroid Build Coastguard Worker return;
180*635a8641SAndroid Build Coastguard Worker
181*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("Close");
182*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
183*635a8641SAndroid Build Coastguard Worker file_.reset();
184*635a8641SAndroid Build Coastguard Worker }
185*635a8641SAndroid Build Coastguard Worker
Seek(Whence whence,int64_t offset)186*635a8641SAndroid Build Coastguard Worker int64_t File::Seek(Whence whence, int64_t offset) {
187*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
188*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
189*635a8641SAndroid Build Coastguard Worker
190*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("Seek", offset);
191*635a8641SAndroid Build Coastguard Worker
192*635a8641SAndroid Build Coastguard Worker // Additionally check __BIONIC__ since older versions of Android don't define
193*635a8641SAndroid Build Coastguard Worker // _FILE_OFFSET_BITS.
194*635a8641SAndroid Build Coastguard Worker #if _FILE_OFFSET_BITS != 64 || defined(__BIONIC__)
195*635a8641SAndroid Build Coastguard Worker static_assert(sizeof(int64_t) == sizeof(off64_t), "off64_t must be 64 bits");
196*635a8641SAndroid Build Coastguard Worker return lseek64(file_.get(), static_cast<off64_t>(offset),
197*635a8641SAndroid Build Coastguard Worker static_cast<int>(whence));
198*635a8641SAndroid Build Coastguard Worker #else
199*635a8641SAndroid Build Coastguard Worker static_assert(sizeof(int64_t) == sizeof(off_t), "off_t must be 64 bits");
200*635a8641SAndroid Build Coastguard Worker return lseek(file_.get(), static_cast<off_t>(offset),
201*635a8641SAndroid Build Coastguard Worker static_cast<int>(whence));
202*635a8641SAndroid Build Coastguard Worker #endif
203*635a8641SAndroid Build Coastguard Worker }
204*635a8641SAndroid Build Coastguard Worker
Read(int64_t offset,char * data,int size)205*635a8641SAndroid Build Coastguard Worker int File::Read(int64_t offset, char* data, int size) {
206*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
207*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
208*635a8641SAndroid Build Coastguard Worker if (size < 0)
209*635a8641SAndroid Build Coastguard Worker return -1;
210*635a8641SAndroid Build Coastguard Worker
211*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("Read", size);
212*635a8641SAndroid Build Coastguard Worker
213*635a8641SAndroid Build Coastguard Worker int bytes_read = 0;
214*635a8641SAndroid Build Coastguard Worker int rv;
215*635a8641SAndroid Build Coastguard Worker do {
216*635a8641SAndroid Build Coastguard Worker rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read,
217*635a8641SAndroid Build Coastguard Worker size - bytes_read, offset + bytes_read));
218*635a8641SAndroid Build Coastguard Worker if (rv <= 0)
219*635a8641SAndroid Build Coastguard Worker break;
220*635a8641SAndroid Build Coastguard Worker
221*635a8641SAndroid Build Coastguard Worker bytes_read += rv;
222*635a8641SAndroid Build Coastguard Worker } while (bytes_read < size);
223*635a8641SAndroid Build Coastguard Worker
224*635a8641SAndroid Build Coastguard Worker return bytes_read ? bytes_read : rv;
225*635a8641SAndroid Build Coastguard Worker }
226*635a8641SAndroid Build Coastguard Worker
ReadAtCurrentPos(char * data,int size)227*635a8641SAndroid Build Coastguard Worker int File::ReadAtCurrentPos(char* data, int size) {
228*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
229*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
230*635a8641SAndroid Build Coastguard Worker if (size < 0)
231*635a8641SAndroid Build Coastguard Worker return -1;
232*635a8641SAndroid Build Coastguard Worker
233*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("ReadAtCurrentPos", size);
234*635a8641SAndroid Build Coastguard Worker
235*635a8641SAndroid Build Coastguard Worker int bytes_read = 0;
236*635a8641SAndroid Build Coastguard Worker int rv;
237*635a8641SAndroid Build Coastguard Worker do {
238*635a8641SAndroid Build Coastguard Worker rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read));
239*635a8641SAndroid Build Coastguard Worker if (rv <= 0)
240*635a8641SAndroid Build Coastguard Worker break;
241*635a8641SAndroid Build Coastguard Worker
242*635a8641SAndroid Build Coastguard Worker bytes_read += rv;
243*635a8641SAndroid Build Coastguard Worker } while (bytes_read < size);
244*635a8641SAndroid Build Coastguard Worker
245*635a8641SAndroid Build Coastguard Worker return bytes_read ? bytes_read : rv;
246*635a8641SAndroid Build Coastguard Worker }
247*635a8641SAndroid Build Coastguard Worker
ReadNoBestEffort(int64_t offset,char * data,int size)248*635a8641SAndroid Build Coastguard Worker int File::ReadNoBestEffort(int64_t offset, char* data, int size) {
249*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
250*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
251*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("ReadNoBestEffort", size);
252*635a8641SAndroid Build Coastguard Worker return HANDLE_EINTR(pread(file_.get(), data, size, offset));
253*635a8641SAndroid Build Coastguard Worker }
254*635a8641SAndroid Build Coastguard Worker
ReadAtCurrentPosNoBestEffort(char * data,int size)255*635a8641SAndroid Build Coastguard Worker int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
256*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
257*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
258*635a8641SAndroid Build Coastguard Worker if (size < 0)
259*635a8641SAndroid Build Coastguard Worker return -1;
260*635a8641SAndroid Build Coastguard Worker
261*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("ReadAtCurrentPosNoBestEffort", size);
262*635a8641SAndroid Build Coastguard Worker return HANDLE_EINTR(read(file_.get(), data, size));
263*635a8641SAndroid Build Coastguard Worker }
264*635a8641SAndroid Build Coastguard Worker
Write(int64_t offset,const char * data,int size)265*635a8641SAndroid Build Coastguard Worker int File::Write(int64_t offset, const char* data, int size) {
266*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
267*635a8641SAndroid Build Coastguard Worker
268*635a8641SAndroid Build Coastguard Worker if (IsOpenAppend(file_.get()))
269*635a8641SAndroid Build Coastguard Worker return WriteAtCurrentPos(data, size);
270*635a8641SAndroid Build Coastguard Worker
271*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
272*635a8641SAndroid Build Coastguard Worker if (size < 0)
273*635a8641SAndroid Build Coastguard Worker return -1;
274*635a8641SAndroid Build Coastguard Worker
275*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("Write", size);
276*635a8641SAndroid Build Coastguard Worker
277*635a8641SAndroid Build Coastguard Worker int bytes_written = 0;
278*635a8641SAndroid Build Coastguard Worker int rv;
279*635a8641SAndroid Build Coastguard Worker do {
280*635a8641SAndroid Build Coastguard Worker #if _FILE_OFFSET_BITS != 64 || defined(__BIONIC__)
281*635a8641SAndroid Build Coastguard Worker // In case __USE_FILE_OFFSET64 is not used, we need to call pwrite64()
282*635a8641SAndroid Build Coastguard Worker // instead of pwrite().
283*635a8641SAndroid Build Coastguard Worker static_assert(sizeof(int64_t) == sizeof(off64_t),
284*635a8641SAndroid Build Coastguard Worker "off64_t must be 64 bits");
285*635a8641SAndroid Build Coastguard Worker rv = HANDLE_EINTR(pwrite64(file_.get(), data + bytes_written,
286*635a8641SAndroid Build Coastguard Worker size - bytes_written, offset + bytes_written));
287*635a8641SAndroid Build Coastguard Worker #else
288*635a8641SAndroid Build Coastguard Worker rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written,
289*635a8641SAndroid Build Coastguard Worker size - bytes_written, offset + bytes_written));
290*635a8641SAndroid Build Coastguard Worker #endif
291*635a8641SAndroid Build Coastguard Worker if (rv <= 0)
292*635a8641SAndroid Build Coastguard Worker break;
293*635a8641SAndroid Build Coastguard Worker
294*635a8641SAndroid Build Coastguard Worker bytes_written += rv;
295*635a8641SAndroid Build Coastguard Worker } while (bytes_written < size);
296*635a8641SAndroid Build Coastguard Worker
297*635a8641SAndroid Build Coastguard Worker return bytes_written ? bytes_written : rv;
298*635a8641SAndroid Build Coastguard Worker }
299*635a8641SAndroid Build Coastguard Worker
WriteAtCurrentPos(const char * data,int size)300*635a8641SAndroid Build Coastguard Worker int File::WriteAtCurrentPos(const char* data, int size) {
301*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
302*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
303*635a8641SAndroid Build Coastguard Worker if (size < 0)
304*635a8641SAndroid Build Coastguard Worker return -1;
305*635a8641SAndroid Build Coastguard Worker
306*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("WriteAtCurrentPos", size);
307*635a8641SAndroid Build Coastguard Worker
308*635a8641SAndroid Build Coastguard Worker int bytes_written = 0;
309*635a8641SAndroid Build Coastguard Worker int rv;
310*635a8641SAndroid Build Coastguard Worker do {
311*635a8641SAndroid Build Coastguard Worker rv = HANDLE_EINTR(write(file_.get(), data + bytes_written,
312*635a8641SAndroid Build Coastguard Worker size - bytes_written));
313*635a8641SAndroid Build Coastguard Worker if (rv <= 0)
314*635a8641SAndroid Build Coastguard Worker break;
315*635a8641SAndroid Build Coastguard Worker
316*635a8641SAndroid Build Coastguard Worker bytes_written += rv;
317*635a8641SAndroid Build Coastguard Worker } while (bytes_written < size);
318*635a8641SAndroid Build Coastguard Worker
319*635a8641SAndroid Build Coastguard Worker return bytes_written ? bytes_written : rv;
320*635a8641SAndroid Build Coastguard Worker }
321*635a8641SAndroid Build Coastguard Worker
WriteAtCurrentPosNoBestEffort(const char * data,int size)322*635a8641SAndroid Build Coastguard Worker int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
323*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
324*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
325*635a8641SAndroid Build Coastguard Worker if (size < 0)
326*635a8641SAndroid Build Coastguard Worker return -1;
327*635a8641SAndroid Build Coastguard Worker
328*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("WriteAtCurrentPosNoBestEffort", size);
329*635a8641SAndroid Build Coastguard Worker return HANDLE_EINTR(write(file_.get(), data, size));
330*635a8641SAndroid Build Coastguard Worker }
331*635a8641SAndroid Build Coastguard Worker
GetLength()332*635a8641SAndroid Build Coastguard Worker int64_t File::GetLength() {
333*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
334*635a8641SAndroid Build Coastguard Worker
335*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("GetLength");
336*635a8641SAndroid Build Coastguard Worker
337*635a8641SAndroid Build Coastguard Worker stat_wrapper_t file_info;
338*635a8641SAndroid Build Coastguard Worker if (CallFstat(file_.get(), &file_info))
339*635a8641SAndroid Build Coastguard Worker return -1;
340*635a8641SAndroid Build Coastguard Worker
341*635a8641SAndroid Build Coastguard Worker return file_info.st_size;
342*635a8641SAndroid Build Coastguard Worker }
343*635a8641SAndroid Build Coastguard Worker
SetLength(int64_t length)344*635a8641SAndroid Build Coastguard Worker bool File::SetLength(int64_t length) {
345*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
346*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
347*635a8641SAndroid Build Coastguard Worker
348*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE_WITH_SIZE("SetLength", length);
349*635a8641SAndroid Build Coastguard Worker return !CallFtruncate(file_.get(), length);
350*635a8641SAndroid Build Coastguard Worker }
351*635a8641SAndroid Build Coastguard Worker
SetTimes(Time last_access_time,Time last_modified_time)352*635a8641SAndroid Build Coastguard Worker bool File::SetTimes(Time last_access_time, Time last_modified_time) {
353*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
354*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
355*635a8641SAndroid Build Coastguard Worker
356*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("SetTimes");
357*635a8641SAndroid Build Coastguard Worker
358*635a8641SAndroid Build Coastguard Worker timeval times[2];
359*635a8641SAndroid Build Coastguard Worker times[0] = last_access_time.ToTimeVal();
360*635a8641SAndroid Build Coastguard Worker times[1] = last_modified_time.ToTimeVal();
361*635a8641SAndroid Build Coastguard Worker
362*635a8641SAndroid Build Coastguard Worker return !CallFutimes(file_.get(), times);
363*635a8641SAndroid Build Coastguard Worker }
364*635a8641SAndroid Build Coastguard Worker
GetInfo(Info * info)365*635a8641SAndroid Build Coastguard Worker bool File::GetInfo(Info* info) {
366*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
367*635a8641SAndroid Build Coastguard Worker
368*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("GetInfo");
369*635a8641SAndroid Build Coastguard Worker
370*635a8641SAndroid Build Coastguard Worker stat_wrapper_t file_info;
371*635a8641SAndroid Build Coastguard Worker if (CallFstat(file_.get(), &file_info))
372*635a8641SAndroid Build Coastguard Worker return false;
373*635a8641SAndroid Build Coastguard Worker
374*635a8641SAndroid Build Coastguard Worker info->FromStat(file_info);
375*635a8641SAndroid Build Coastguard Worker return true;
376*635a8641SAndroid Build Coastguard Worker }
377*635a8641SAndroid Build Coastguard Worker
378*635a8641SAndroid Build Coastguard Worker #if !defined(OS_FUCHSIA)
Lock()379*635a8641SAndroid Build Coastguard Worker File::Error File::Lock() {
380*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("Lock");
381*635a8641SAndroid Build Coastguard Worker return CallFcntlFlock(file_.get(), true);
382*635a8641SAndroid Build Coastguard Worker }
383*635a8641SAndroid Build Coastguard Worker
Unlock()384*635a8641SAndroid Build Coastguard Worker File::Error File::Unlock() {
385*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("Unlock");
386*635a8641SAndroid Build Coastguard Worker return CallFcntlFlock(file_.get(), false);
387*635a8641SAndroid Build Coastguard Worker }
388*635a8641SAndroid Build Coastguard Worker #endif
389*635a8641SAndroid Build Coastguard Worker
Duplicate() const390*635a8641SAndroid Build Coastguard Worker File File::Duplicate() const {
391*635a8641SAndroid Build Coastguard Worker if (!IsValid())
392*635a8641SAndroid Build Coastguard Worker return File();
393*635a8641SAndroid Build Coastguard Worker
394*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("Duplicate");
395*635a8641SAndroid Build Coastguard Worker
396*635a8641SAndroid Build Coastguard Worker PlatformFile other_fd = HANDLE_EINTR(dup(GetPlatformFile()));
397*635a8641SAndroid Build Coastguard Worker if (other_fd == -1)
398*635a8641SAndroid Build Coastguard Worker return File(File::GetLastFileError());
399*635a8641SAndroid Build Coastguard Worker
400*635a8641SAndroid Build Coastguard Worker return File(other_fd, async());
401*635a8641SAndroid Build Coastguard Worker }
402*635a8641SAndroid Build Coastguard Worker
403*635a8641SAndroid Build Coastguard Worker // Static.
OSErrorToFileError(int saved_errno)404*635a8641SAndroid Build Coastguard Worker File::Error File::OSErrorToFileError(int saved_errno) {
405*635a8641SAndroid Build Coastguard Worker switch (saved_errno) {
406*635a8641SAndroid Build Coastguard Worker case EACCES:
407*635a8641SAndroid Build Coastguard Worker case EISDIR:
408*635a8641SAndroid Build Coastguard Worker case EROFS:
409*635a8641SAndroid Build Coastguard Worker case EPERM:
410*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_ACCESS_DENIED;
411*635a8641SAndroid Build Coastguard Worker case EBUSY:
412*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL) // ETXTBSY not defined by NaCl.
413*635a8641SAndroid Build Coastguard Worker case ETXTBSY:
414*635a8641SAndroid Build Coastguard Worker #endif
415*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_IN_USE;
416*635a8641SAndroid Build Coastguard Worker case EEXIST:
417*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_EXISTS;
418*635a8641SAndroid Build Coastguard Worker case EIO:
419*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_IO;
420*635a8641SAndroid Build Coastguard Worker case ENOENT:
421*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_NOT_FOUND;
422*635a8641SAndroid Build Coastguard Worker case ENFILE: // fallthrough
423*635a8641SAndroid Build Coastguard Worker case EMFILE:
424*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_TOO_MANY_OPENED;
425*635a8641SAndroid Build Coastguard Worker case ENOMEM:
426*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_NO_MEMORY;
427*635a8641SAndroid Build Coastguard Worker case ENOSPC:
428*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_NO_SPACE;
429*635a8641SAndroid Build Coastguard Worker case ENOTDIR:
430*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_NOT_A_DIRECTORY;
431*635a8641SAndroid Build Coastguard Worker default:
432*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL) // NaCl build has no metrics code.
433*635a8641SAndroid Build Coastguard Worker UmaHistogramSparse("PlatformFile.UnknownErrors.Posix", saved_errno);
434*635a8641SAndroid Build Coastguard Worker #endif
435*635a8641SAndroid Build Coastguard Worker // This function should only be called for errors.
436*635a8641SAndroid Build Coastguard Worker DCHECK_NE(0, saved_errno);
437*635a8641SAndroid Build Coastguard Worker return FILE_ERROR_FAILED;
438*635a8641SAndroid Build Coastguard Worker }
439*635a8641SAndroid Build Coastguard Worker }
440*635a8641SAndroid Build Coastguard Worker
441*635a8641SAndroid Build Coastguard Worker // NaCl doesn't implement system calls to open files directly.
442*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL)
443*635a8641SAndroid Build Coastguard Worker // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
DoInitialize(const FilePath & path,uint32_t flags)444*635a8641SAndroid Build Coastguard Worker void File::DoInitialize(const FilePath& path, uint32_t flags) {
445*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
446*635a8641SAndroid Build Coastguard Worker DCHECK(!IsValid());
447*635a8641SAndroid Build Coastguard Worker
448*635a8641SAndroid Build Coastguard Worker int open_flags = 0;
449*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_CREATE)
450*635a8641SAndroid Build Coastguard Worker open_flags = O_CREAT | O_EXCL;
451*635a8641SAndroid Build Coastguard Worker
452*635a8641SAndroid Build Coastguard Worker created_ = false;
453*635a8641SAndroid Build Coastguard Worker
454*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_CREATE_ALWAYS) {
455*635a8641SAndroid Build Coastguard Worker DCHECK(!open_flags);
456*635a8641SAndroid Build Coastguard Worker DCHECK(flags & FLAG_WRITE);
457*635a8641SAndroid Build Coastguard Worker open_flags = O_CREAT | O_TRUNC;
458*635a8641SAndroid Build Coastguard Worker }
459*635a8641SAndroid Build Coastguard Worker
460*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_OPEN_TRUNCATED) {
461*635a8641SAndroid Build Coastguard Worker DCHECK(!open_flags);
462*635a8641SAndroid Build Coastguard Worker DCHECK(flags & FLAG_WRITE);
463*635a8641SAndroid Build Coastguard Worker open_flags = O_TRUNC;
464*635a8641SAndroid Build Coastguard Worker }
465*635a8641SAndroid Build Coastguard Worker
466*635a8641SAndroid Build Coastguard Worker if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
467*635a8641SAndroid Build Coastguard Worker NOTREACHED();
468*635a8641SAndroid Build Coastguard Worker errno = EOPNOTSUPP;
469*635a8641SAndroid Build Coastguard Worker error_details_ = FILE_ERROR_FAILED;
470*635a8641SAndroid Build Coastguard Worker return;
471*635a8641SAndroid Build Coastguard Worker }
472*635a8641SAndroid Build Coastguard Worker
473*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_WRITE && flags & FLAG_READ) {
474*635a8641SAndroid Build Coastguard Worker open_flags |= O_RDWR;
475*635a8641SAndroid Build Coastguard Worker } else if (flags & FLAG_WRITE) {
476*635a8641SAndroid Build Coastguard Worker open_flags |= O_WRONLY;
477*635a8641SAndroid Build Coastguard Worker } else if (!(flags & FLAG_READ) &&
478*635a8641SAndroid Build Coastguard Worker !(flags & FLAG_WRITE_ATTRIBUTES) &&
479*635a8641SAndroid Build Coastguard Worker !(flags & FLAG_APPEND) &&
480*635a8641SAndroid Build Coastguard Worker !(flags & FLAG_OPEN_ALWAYS)) {
481*635a8641SAndroid Build Coastguard Worker NOTREACHED();
482*635a8641SAndroid Build Coastguard Worker }
483*635a8641SAndroid Build Coastguard Worker
484*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_TERMINAL_DEVICE)
485*635a8641SAndroid Build Coastguard Worker open_flags |= O_NOCTTY | O_NDELAY;
486*635a8641SAndroid Build Coastguard Worker
487*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_APPEND && flags & FLAG_READ)
488*635a8641SAndroid Build Coastguard Worker open_flags |= O_APPEND | O_RDWR;
489*635a8641SAndroid Build Coastguard Worker else if (flags & FLAG_APPEND)
490*635a8641SAndroid Build Coastguard Worker open_flags |= O_APPEND | O_WRONLY;
491*635a8641SAndroid Build Coastguard Worker
492*635a8641SAndroid Build Coastguard Worker static_assert(O_RDONLY == 0, "O_RDONLY must equal zero");
493*635a8641SAndroid Build Coastguard Worker
494*635a8641SAndroid Build Coastguard Worker int mode = S_IRUSR | S_IWUSR;
495*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
496*635a8641SAndroid Build Coastguard Worker mode |= S_IRGRP | S_IROTH;
497*635a8641SAndroid Build Coastguard Worker #endif
498*635a8641SAndroid Build Coastguard Worker
499*635a8641SAndroid Build Coastguard Worker int descriptor = HANDLE_EINTR(open(path.value().c_str(), open_flags, mode));
500*635a8641SAndroid Build Coastguard Worker
501*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_OPEN_ALWAYS) {
502*635a8641SAndroid Build Coastguard Worker if (descriptor < 0) {
503*635a8641SAndroid Build Coastguard Worker open_flags |= O_CREAT;
504*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
505*635a8641SAndroid Build Coastguard Worker open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
506*635a8641SAndroid Build Coastguard Worker
507*635a8641SAndroid Build Coastguard Worker descriptor = HANDLE_EINTR(open(path.value().c_str(), open_flags, mode));
508*635a8641SAndroid Build Coastguard Worker if (descriptor >= 0)
509*635a8641SAndroid Build Coastguard Worker created_ = true;
510*635a8641SAndroid Build Coastguard Worker }
511*635a8641SAndroid Build Coastguard Worker }
512*635a8641SAndroid Build Coastguard Worker
513*635a8641SAndroid Build Coastguard Worker if (descriptor < 0) {
514*635a8641SAndroid Build Coastguard Worker error_details_ = File::GetLastFileError();
515*635a8641SAndroid Build Coastguard Worker return;
516*635a8641SAndroid Build Coastguard Worker }
517*635a8641SAndroid Build Coastguard Worker
518*635a8641SAndroid Build Coastguard Worker if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
519*635a8641SAndroid Build Coastguard Worker created_ = true;
520*635a8641SAndroid Build Coastguard Worker
521*635a8641SAndroid Build Coastguard Worker if (flags & FLAG_DELETE_ON_CLOSE)
522*635a8641SAndroid Build Coastguard Worker unlink(path.value().c_str());
523*635a8641SAndroid Build Coastguard Worker
524*635a8641SAndroid Build Coastguard Worker async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
525*635a8641SAndroid Build Coastguard Worker error_details_ = FILE_OK;
526*635a8641SAndroid Build Coastguard Worker file_.reset(descriptor);
527*635a8641SAndroid Build Coastguard Worker }
528*635a8641SAndroid Build Coastguard Worker #endif // !defined(OS_NACL)
529*635a8641SAndroid Build Coastguard Worker
Flush()530*635a8641SAndroid Build Coastguard Worker bool File::Flush() {
531*635a8641SAndroid Build Coastguard Worker AssertBlockingAllowed();
532*635a8641SAndroid Build Coastguard Worker DCHECK(IsValid());
533*635a8641SAndroid Build Coastguard Worker SCOPED_FILE_TRACE("Flush");
534*635a8641SAndroid Build Coastguard Worker
535*635a8641SAndroid Build Coastguard Worker #if defined(OS_NACL)
536*635a8641SAndroid Build Coastguard Worker NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
537*635a8641SAndroid Build Coastguard Worker return true;
538*635a8641SAndroid Build Coastguard Worker #elif defined(OS_LINUX) || defined(OS_ANDROID)
539*635a8641SAndroid Build Coastguard Worker return !HANDLE_EINTR(fdatasync(file_.get()));
540*635a8641SAndroid Build Coastguard Worker #else
541*635a8641SAndroid Build Coastguard Worker return !HANDLE_EINTR(fsync(file_.get()));
542*635a8641SAndroid Build Coastguard Worker #endif
543*635a8641SAndroid Build Coastguard Worker }
544*635a8641SAndroid Build Coastguard Worker
SetPlatformFile(PlatformFile file)545*635a8641SAndroid Build Coastguard Worker void File::SetPlatformFile(PlatformFile file) {
546*635a8641SAndroid Build Coastguard Worker DCHECK(!file_.is_valid());
547*635a8641SAndroid Build Coastguard Worker file_.reset(file);
548*635a8641SAndroid Build Coastguard Worker }
549*635a8641SAndroid Build Coastguard Worker
550*635a8641SAndroid Build Coastguard Worker // static
GetLastFileError()551*635a8641SAndroid Build Coastguard Worker File::Error File::GetLastFileError() {
552*635a8641SAndroid Build Coastguard Worker return base::File::OSErrorToFileError(errno);
553*635a8641SAndroid Build Coastguard Worker }
554*635a8641SAndroid Build Coastguard Worker
555*635a8641SAndroid Build Coastguard Worker } // namespace base
556