Initialize Tizen 2.3
[external/chromium.git] / base / platform_file_posix.cc
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/platform_file.h"
6
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11
12 #include "base/eintr_wrapper.h"
13 #include "base/file_path.h"
14 #include "base/logging.h"
15 #include "base/utf_string_conversions.h"
16
17 #if defined(OS_ANDROID)
18 #include "base/os_compat_android.h"
19 #endif
20
21 namespace base {
22
23 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) || \
24     (defined(OS_MACOSX) && \
25      MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
26 typedef struct stat stat_wrapper_t;
27 static int CallFstat(int fd, stat_wrapper_t *sb) {
28   return fstat(fd, sb);
29 }
30 #else
31 typedef struct stat64 stat_wrapper_t;
32 static int CallFstat(int fd, stat_wrapper_t *sb) {
33   return fstat64(fd, sb);
34 }
35 #endif
36
37 // TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
38 PlatformFile CreatePlatformFile(const FilePath& name, int flags,
39                                 bool* created, PlatformFileError* error_code) {
40   int open_flags = 0;
41   if (flags & PLATFORM_FILE_CREATE)
42     open_flags = O_CREAT | O_EXCL;
43
44   if (created)
45     *created = false;
46
47   if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
48     DCHECK(!open_flags);
49     open_flags = O_CREAT | O_TRUNC;
50   }
51
52   if (flags & PLATFORM_FILE_OPEN_TRUNCATED) {
53     DCHECK(!open_flags);
54     DCHECK(flags & PLATFORM_FILE_WRITE);
55     open_flags = O_TRUNC;
56   }
57
58   if (!open_flags && !(flags & PLATFORM_FILE_OPEN) &&
59       !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
60     NOTREACHED();
61     errno = EOPNOTSUPP;
62     if (error_code)
63       *error_code = PLATFORM_FILE_ERROR_FAILED;
64     return kInvalidPlatformFileValue;
65   }
66
67   if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) {
68     open_flags |= O_RDWR;
69   } else if (flags & PLATFORM_FILE_WRITE) {
70     open_flags |= O_WRONLY;
71   } else if (!(flags & PLATFORM_FILE_READ) &&
72              !(flags & PLATFORM_FILE_WRITE_ATTRIBUTES) &&
73              !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
74     NOTREACHED();
75   }
76
77   COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
78
79   int descriptor =
80       HANDLE_EINTR(open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR));
81
82   if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
83     if (descriptor <= 0) {
84       open_flags |= O_CREAT;
85       if (flags & PLATFORM_FILE_EXCLUSIVE_READ ||
86           flags & PLATFORM_FILE_EXCLUSIVE_WRITE) {
87         open_flags |= O_EXCL;   // together with O_CREAT implies O_NOFOLLOW
88       }
89       descriptor = HANDLE_EINTR(
90           open(name.value().c_str(), open_flags, S_IRUSR | S_IWUSR));
91       if (created && descriptor > 0)
92         *created = true;
93     }
94   }
95
96   if (created && (descriptor > 0) &&
97       (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)))
98     *created = true;
99
100   if ((descriptor > 0) && (flags & PLATFORM_FILE_DELETE_ON_CLOSE)) {
101     unlink(name.value().c_str());
102   }
103
104   if (error_code) {
105     if (descriptor >= 0)
106       *error_code = PLATFORM_FILE_OK;
107     else {
108       switch (errno) {
109         case EACCES:
110         case EISDIR:
111         case EROFS:
112         case EPERM:
113           *error_code = PLATFORM_FILE_ERROR_ACCESS_DENIED;
114           break;
115         case ETXTBSY:
116           *error_code = PLATFORM_FILE_ERROR_IN_USE;
117           break;
118         case EEXIST:
119           *error_code = PLATFORM_FILE_ERROR_EXISTS;
120           break;
121         case ENOENT:
122           *error_code = PLATFORM_FILE_ERROR_NOT_FOUND;
123           break;
124         case EMFILE:
125           *error_code = PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
126           break;
127         case ENOMEM:
128           *error_code = PLATFORM_FILE_ERROR_NO_MEMORY;
129           break;
130         case ENOSPC:
131           *error_code = PLATFORM_FILE_ERROR_NO_SPACE;
132           break;
133         case ENOTDIR:
134           *error_code = PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
135           break;
136         default:
137           *error_code = PLATFORM_FILE_ERROR_FAILED;
138       }
139     }
140   }
141
142   return descriptor;
143 }
144
145 bool ClosePlatformFile(PlatformFile file) {
146   return !HANDLE_EINTR(close(file));
147 }
148
149 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
150   if (file < 0)
151     return -1;
152
153   return HANDLE_EINTR(pread(file, data, size, offset));
154 }
155
156 int WritePlatformFile(PlatformFile file, int64 offset,
157                       const char* data, int size) {
158   if (file < 0)
159     return -1;
160
161   return HANDLE_EINTR(pwrite(file, data, size, offset));
162 }
163
164 bool TruncatePlatformFile(PlatformFile file, int64 length) {
165   return ((file >= 0) && !HANDLE_EINTR(ftruncate(file, length)));
166 }
167
168 bool FlushPlatformFile(PlatformFile file) {
169   return !HANDLE_EINTR(fsync(file));
170 }
171
172 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
173                        const base::Time& last_modified_time) {
174   if (file < 0)
175     return false;
176
177   timeval times[2];
178   times[0] = last_access_time.ToTimeVal();
179   times[1] = last_modified_time.ToTimeVal();
180   return !futimes(file, times);
181 }
182
183 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
184   if (!info)
185     return false;
186
187   stat_wrapper_t file_info;
188   if (CallFstat(file, &file_info))
189     return false;
190
191   info->is_directory = S_ISDIR(file_info.st_mode);
192   info->is_symbolic_link = S_ISLNK(file_info.st_mode);
193   info->size = file_info.st_size;
194   info->last_modified = base::Time::FromTimeT(file_info.st_mtime);
195   info->last_accessed = base::Time::FromTimeT(file_info.st_atime);
196   info->creation_time = base::Time::FromTimeT(file_info.st_ctime);
197   return true;
198 }
199
200 }  // namespace base