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

Side by Side Diff: base/platform_file_posix.cc

Issue 17779003: Port base/files/file_util_proxy to Native Client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix build when __USE_XOPEN2K8 is defined. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/platform_file.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/platform_file.h" 5 #include "base/platform_file.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <errno.h> 8 #include <errno.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/logging.h" 13 #include "base/logging.h"
14 #include "base/metrics/sparse_histogram.h" 14 #include "base/metrics/sparse_histogram.h"
15 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
16 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 18
19 #if defined(OS_ANDROID) 19 #if defined(OS_ANDROID)
20 #include "base/os_compat_android.h" 20 #include "base/os_compat_android.h"
21 #endif 21 #endif
22 22
23 namespace base { 23 namespace base {
24 24
25 // Make sure our Whence mappings match the system headers. 25 // Make sure our Whence mappings match the system headers.
26 COMPILE_ASSERT(PLATFORM_FILE_FROM_BEGIN == SEEK_SET && 26 COMPILE_ASSERT(PLATFORM_FILE_FROM_BEGIN == SEEK_SET &&
27 PLATFORM_FILE_FROM_CURRENT == SEEK_CUR && 27 PLATFORM_FILE_FROM_CURRENT == SEEK_CUR &&
28 PLATFORM_FILE_FROM_END == SEEK_END, whence_matches_system); 28 PLATFORM_FILE_FROM_END == SEEK_END, whence_matches_system);
29 29
30 #if defined(OS_BSD) || defined(OS_MACOSX) 30 namespace {
31
32 #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
31 typedef struct stat stat_wrapper_t; 33 typedef struct stat stat_wrapper_t;
32 static int CallFstat(int fd, stat_wrapper_t *sb) { 34 static int CallFstat(int fd, stat_wrapper_t *sb) {
33 base::ThreadRestrictions::AssertIOAllowed(); 35 base::ThreadRestrictions::AssertIOAllowed();
34 return fstat(fd, sb); 36 return fstat(fd, sb);
35 } 37 }
36 #else 38 #else
37 typedef struct stat64 stat_wrapper_t; 39 typedef struct stat64 stat_wrapper_t;
38 static int CallFstat(int fd, stat_wrapper_t *sb) { 40 static int CallFstat(int fd, stat_wrapper_t *sb) {
39 base::ThreadRestrictions::AssertIOAllowed(); 41 base::ThreadRestrictions::AssertIOAllowed();
40 return fstat64(fd, sb); 42 return fstat64(fd, sb);
41 } 43 }
42 #endif 44 #endif
43 45
46 // TODO(bbudge) Remove NaCl workarounds when it implements pread and pwrite.
brettw 2013/07/11 18:02:43 Probably this comment should be more generic (sinc
bbudge 2013/07/11 20:08:23 I moved the comment to just above DoPread. It's li
bbudge 2013/07/11 20:13:18 Added comments about why these are necessary.
47 #if !defined(OS_NACL)
48 static int DoPread(PlatformFile file, char* data, int size, int64 offset) {
49 return HANDLE_EINTR(pread(file, data, size, offset));
50 }
51
52 static int DoPwrite(PlatformFile file, const char* data, int size,
53 int64 offset) {
54 return HANDLE_EINTR(pwrite(file, data, size, offset));
55 }
56
57 static bool IsOpenAppend(PlatformFile file) {
58 return (fcntl(file, F_GETFL) & O_APPEND) != 0;
59 }
60
61 static int CallFtruncate(PlatformFile file, int64 length) {
62 return HANDLE_EINTR(ftruncate(file, length));
63 }
64
65 static int CallFsync(PlatformFile file) {
66 return HANDLE_EINTR(fsync(file));
67 }
68
69 static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
70 #ifdef __USE_XOPEN2K8
71 // futimens should be available, but futimes might not be
72 // http://pubs.opengroup.org/onlinepubs/9699919799/
73
74 timespec ts_times[2];
75 ts_times[0].tv_sec = times[0].tv_sec;
76 ts_times[0].tv_nsec = times[0].tv_usec * 1000;
77 ts_times[1].tv_sec = times[1].tv_sec;
78 ts_times[1].tv_nsec = times[1].tv_usec * 1000;
79
80 return futimens(file, ts_times);
81 #else
82 return futimes(file, times);
83 #endif
84 }
85 #else
86 static int DoPread(PlatformFile file, char* data, int size, int64 offset) {
87 lseek(file, static_cast<off_t>(offset), SEEK_SET);
88 return HANDLE_EINTR(read(file, data, size));
89 }
90
91 static int DoPwrite(PlatformFile file, const char* data, int size,
92 int64 offset) {
93 lseek(file, static_cast<off_t>(offset), SEEK_SET);
94 return HANDLE_EINTR(write(file, data, size));
95 }
96
97 static bool IsOpenAppend(PlatformFile file) {
98 // NaCl doesn't implement fcntl. Since NaCl's write conforms to the POSIX
99 // standard and always appends if the file is opened with O_APPEND, just
100 // return false here.
101 return false;
102 }
103
104 static int CallFtruncate(PlatformFile file, int64 length) {
105 NOTIMPLEMENTED(); // NaCl doesn't implement ftruncate.
106 return 0;
107 }
108
109 static int CallFsync(PlatformFile file) {
110 NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
111 return 0;
112 }
113
114 static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
115 NOTIMPLEMENTED(); // NaCl doesn't implement futimes.
116 return 0;
117 }
118 #endif // !defined(OS_NACL)
119
120 } // namespace
121
122 // NaCl doesn't implement system calls to open files directly.
123 #if !defined(OS_NACL)
44 // TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here? 124 // TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
45 PlatformFile CreatePlatformFileUnsafe(const FilePath& name, 125 PlatformFile CreatePlatformFileUnsafe(const FilePath& name,
46 int flags, 126 int flags,
47 bool* created, 127 bool* created,
48 PlatformFileError* error) { 128 PlatformFileError* error) {
49 base::ThreadRestrictions::AssertIOAllowed(); 129 base::ThreadRestrictions::AssertIOAllowed();
50 130
51 int open_flags = 0; 131 int open_flags = 0;
52 if (flags & PLATFORM_FILE_CREATE) 132 if (flags & PLATFORM_FILE_CREATE)
53 open_flags = O_CREAT | O_EXCL; 133 open_flags = O_CREAT | O_EXCL;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 else 212 else
133 *error = ErrnoToPlatformFileError(errno); 213 *error = ErrnoToPlatformFileError(errno);
134 } 214 }
135 215
136 return descriptor; 216 return descriptor;
137 } 217 }
138 218
139 FILE* FdopenPlatformFile(PlatformFile file, const char* mode) { 219 FILE* FdopenPlatformFile(PlatformFile file, const char* mode) {
140 return fdopen(file, mode); 220 return fdopen(file, mode);
141 } 221 }
222 #endif // !defined(OS_NACL)
142 223
143 bool ClosePlatformFile(PlatformFile file) { 224 bool ClosePlatformFile(PlatformFile file) {
144 base::ThreadRestrictions::AssertIOAllowed(); 225 base::ThreadRestrictions::AssertIOAllowed();
145 return !HANDLE_EINTR(close(file)); 226 return !HANDLE_EINTR(close(file));
146 } 227 }
147 228
148 int64 SeekPlatformFile(PlatformFile file, 229 int64 SeekPlatformFile(PlatformFile file,
149 PlatformFileWhence whence, 230 PlatformFileWhence whence,
150 int64 offset) { 231 int64 offset) {
151 base::ThreadRestrictions::AssertIOAllowed(); 232 base::ThreadRestrictions::AssertIOAllowed();
152 if (file < 0 || offset < 0) 233 if (file < 0 || offset < 0)
153 return -1; 234 return -1;
154 235
155 return lseek(file, static_cast<off_t>(offset), static_cast<int>(whence)); 236 return lseek(file, static_cast<off_t>(offset), static_cast<int>(whence));
156 } 237 }
157 238
158 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { 239 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
159 base::ThreadRestrictions::AssertIOAllowed(); 240 base::ThreadRestrictions::AssertIOAllowed();
160 if (file < 0 || size < 0) 241 if (file < 0 || size < 0)
161 return -1; 242 return -1;
162 243
163 int bytes_read = 0; 244 int bytes_read = 0;
164 int rv; 245 int rv;
165 do { 246 do {
166 rv = HANDLE_EINTR(pread(file, data + bytes_read, 247 rv = DoPread(file, data + bytes_read,
167 size - bytes_read, offset + bytes_read)); 248 size - bytes_read, offset + bytes_read);
168 if (rv <= 0) 249 if (rv <= 0)
169 break; 250 break;
170 251
171 bytes_read += rv; 252 bytes_read += rv;
172 } while (bytes_read < size); 253 } while (bytes_read < size);
173 254
174 return bytes_read ? bytes_read : rv; 255 return bytes_read ? bytes_read : rv;
175 } 256 }
176 257
177 int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) { 258 int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) {
(...skipping 13 matching lines...) Expand all
191 272
192 return bytes_read ? bytes_read : rv; 273 return bytes_read ? bytes_read : rv;
193 } 274 }
194 275
195 int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, 276 int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset,
196 char* data, int size) { 277 char* data, int size) {
197 base::ThreadRestrictions::AssertIOAllowed(); 278 base::ThreadRestrictions::AssertIOAllowed();
198 if (file < 0) 279 if (file < 0)
199 return -1; 280 return -1;
200 281
201 return HANDLE_EINTR(pread(file, data, size, offset)); 282 return DoPread(file, data, size, offset);
202 } 283 }
203 284
204 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, 285 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file,
205 char* data, int size) { 286 char* data, int size) {
206 base::ThreadRestrictions::AssertIOAllowed(); 287 base::ThreadRestrictions::AssertIOAllowed();
207 if (file < 0 || size < 0) 288 if (file < 0 || size < 0)
208 return -1; 289 return -1;
209 290
210 return HANDLE_EINTR(read(file, data, size)); 291 return HANDLE_EINTR(read(file, data, size));
211 } 292 }
212 293
213 int WritePlatformFile(PlatformFile file, int64 offset, 294 int WritePlatformFile(PlatformFile file, int64 offset,
214 const char* data, int size) { 295 const char* data, int size) {
215 base::ThreadRestrictions::AssertIOAllowed(); 296 base::ThreadRestrictions::AssertIOAllowed();
216 297
217 if (fcntl(file, F_GETFL) & O_APPEND) 298 if (IsOpenAppend(file))
218 return WritePlatformFileAtCurrentPos(file, data, size); 299 return WritePlatformFileAtCurrentPos(file, data, size);
219 300
220 if (file < 0 || size < 0) 301 if (file < 0 || size < 0)
221 return -1; 302 return -1;
222 303
223 int bytes_written = 0; 304 int bytes_written = 0;
224 int rv; 305 int rv;
225 do { 306 do {
226 rv = HANDLE_EINTR(pwrite(file, data + bytes_written, 307 rv = DoPwrite(file, data + bytes_written,
227 size - bytes_written, offset + bytes_written)); 308 size - bytes_written, offset + bytes_written);
228 if (rv <= 0) 309 if (rv <= 0)
229 break; 310 break;
230 311
231 bytes_written += rv; 312 bytes_written += rv;
232 } while (bytes_written < size); 313 } while (bytes_written < size);
233 314
234 return bytes_written ? bytes_written : rv; 315 return bytes_written ? bytes_written : rv;
235 } 316 }
236 317
237 int WritePlatformFileAtCurrentPos(PlatformFile file, 318 int WritePlatformFileAtCurrentPos(PlatformFile file,
(...skipping 19 matching lines...) Expand all
257 const char* data, int size) { 338 const char* data, int size) {
258 base::ThreadRestrictions::AssertIOAllowed(); 339 base::ThreadRestrictions::AssertIOAllowed();
259 if (file < 0 || size < 0) 340 if (file < 0 || size < 0)
260 return -1; 341 return -1;
261 342
262 return HANDLE_EINTR(write(file, data, size)); 343 return HANDLE_EINTR(write(file, data, size));
263 } 344 }
264 345
265 bool TruncatePlatformFile(PlatformFile file, int64 length) { 346 bool TruncatePlatformFile(PlatformFile file, int64 length) {
266 base::ThreadRestrictions::AssertIOAllowed(); 347 base::ThreadRestrictions::AssertIOAllowed();
267 return ((file >= 0) && !HANDLE_EINTR(ftruncate(file, length))); 348 return ((file >= 0) && !CallFtruncate(file, length));
268 } 349 }
269 350
270 bool FlushPlatformFile(PlatformFile file) { 351 bool FlushPlatformFile(PlatformFile file) {
271 base::ThreadRestrictions::AssertIOAllowed(); 352 base::ThreadRestrictions::AssertIOAllowed();
272 return !HANDLE_EINTR(fsync(file)); 353 return !CallFsync(file);
273 } 354 }
274 355
275 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time, 356 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
276 const base::Time& last_modified_time) { 357 const base::Time& last_modified_time) {
277 base::ThreadRestrictions::AssertIOAllowed(); 358 base::ThreadRestrictions::AssertIOAllowed();
278 if (file < 0) 359 if (file < 0)
279 return false; 360 return false;
280 361
281 timeval times[2]; 362 timeval times[2];
282 times[0] = last_access_time.ToTimeVal(); 363 times[0] = last_access_time.ToTimeVal();
283 times[1] = last_modified_time.ToTimeVal(); 364 times[1] = last_modified_time.ToTimeVal();
284 365
285 #ifdef __USE_XOPEN2K8 366 return !CallFutimes(file, times);
286 // futimens should be available, but futimes might not be
287 // http://pubs.opengroup.org/onlinepubs/9699919799/
288
289 timespec ts_times[2];
290 ts_times[0].tv_sec = times[0].tv_sec;
291 ts_times[0].tv_nsec = times[0].tv_usec * 1000;
292 ts_times[1].tv_sec = times[1].tv_sec;
293 ts_times[1].tv_nsec = times[1].tv_usec * 1000;
294
295 return !futimens(file, ts_times);
296 #else
297 return !futimes(file, times);
298 #endif
299 } 367 }
300 368
301 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { 369 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
302 if (!info) 370 if (!info)
303 return false; 371 return false;
304 372
305 stat_wrapper_t file_info; 373 stat_wrapper_t file_info;
306 if (CallFstat(file, &file_info)) 374 if (CallFstat(file, &file_info))
307 return false; 375 return false;
308 376
309 info->is_directory = S_ISDIR(file_info.st_mode); 377 info->is_directory = S_ISDIR(file_info.st_mode);
310 info->is_symbolic_link = S_ISLNK(file_info.st_mode); 378 info->is_symbolic_link = S_ISLNK(file_info.st_mode);
311 info->size = file_info.st_size; 379 info->size = file_info.st_size;
312 info->last_modified = base::Time::FromTimeT(file_info.st_mtime); 380 info->last_modified = base::Time::FromTimeT(file_info.st_mtime);
313 info->last_accessed = base::Time::FromTimeT(file_info.st_atime); 381 info->last_accessed = base::Time::FromTimeT(file_info.st_atime);
314 info->creation_time = base::Time::FromTimeT(file_info.st_ctime); 382 info->creation_time = base::Time::FromTimeT(file_info.st_ctime);
315 return true; 383 return true;
316 } 384 }
317 385
318 PlatformFileError ErrnoToPlatformFileError(int saved_errno) { 386 PlatformFileError ErrnoToPlatformFileError(int saved_errno) {
319 switch (saved_errno) { 387 switch (saved_errno) {
320 case EACCES: 388 case EACCES:
321 case EISDIR: 389 case EISDIR:
322 case EROFS: 390 case EROFS:
323 case EPERM: 391 case EPERM:
324 return PLATFORM_FILE_ERROR_ACCESS_DENIED; 392 return PLATFORM_FILE_ERROR_ACCESS_DENIED;
393 #if !defined(OS_NACL) // ETXTBSY not defined by NaCl.
325 case ETXTBSY: 394 case ETXTBSY:
326 return PLATFORM_FILE_ERROR_IN_USE; 395 return PLATFORM_FILE_ERROR_IN_USE;
396 #endif
327 case EEXIST: 397 case EEXIST:
328 return PLATFORM_FILE_ERROR_EXISTS; 398 return PLATFORM_FILE_ERROR_EXISTS;
329 case ENOENT: 399 case ENOENT:
330 return PLATFORM_FILE_ERROR_NOT_FOUND; 400 return PLATFORM_FILE_ERROR_NOT_FOUND;
331 case EMFILE: 401 case EMFILE:
332 return PLATFORM_FILE_ERROR_TOO_MANY_OPENED; 402 return PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
333 case ENOMEM: 403 case ENOMEM:
334 return PLATFORM_FILE_ERROR_NO_MEMORY; 404 return PLATFORM_FILE_ERROR_NO_MEMORY;
335 case ENOSPC: 405 case ENOSPC:
336 return PLATFORM_FILE_ERROR_NO_SPACE; 406 return PLATFORM_FILE_ERROR_NO_SPACE;
337 case ENOTDIR: 407 case ENOTDIR:
338 return PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; 408 return PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
339 default: 409 default:
340 #if !defined(OS_NACL) // NaCl build has no metrics code. 410 #if !defined(OS_NACL) // NaCl build has no metrics code.
341 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Posix", 411 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Posix",
342 saved_errno); 412 saved_errno);
343 #endif 413 #endif
344 return PLATFORM_FILE_ERROR_FAILED; 414 return PLATFORM_FILE_ERROR_FAILED;
345 } 415 }
346 } 416 }
347 417
348 } // namespace base 418 } // namespace base
OLDNEW
« no previous file with comments | « base/platform_file.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698