/src/brpc/src/butil/files/file.h
Line | Count | Source |
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 |
3 | | // found in the LICENSE file. |
4 | | |
5 | | #ifndef BUTIL_FILES_FILE_H_ |
6 | | #define BUTIL_FILES_FILE_H_ |
7 | | |
8 | | #include "butil/build_config.h" |
9 | | #if defined(OS_WIN) |
10 | | #include <windows.h> |
11 | | #endif |
12 | | |
13 | | #if defined(OS_POSIX) |
14 | | #include <sys/stat.h> |
15 | | #endif |
16 | | |
17 | | #include <string> |
18 | | |
19 | | #include "butil/base_export.h" |
20 | | #include "butil/basictypes.h" |
21 | | #include "butil/files/scoped_file.h" |
22 | | #include "butil/move.h" |
23 | | #include "butil/time/time.h" |
24 | | |
25 | | #if defined(OS_WIN) |
26 | | #include "butil/win/scoped_handle.h" |
27 | | #endif |
28 | | |
29 | | namespace butil { |
30 | | |
31 | | class FilePath; |
32 | | |
33 | | #if defined(OS_WIN) |
34 | | typedef HANDLE PlatformFile; |
35 | | #elif defined(OS_POSIX) |
36 | | typedef int PlatformFile; |
37 | | |
38 | | #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) |
39 | | typedef struct stat stat_wrapper_t; |
40 | | #else |
41 | | typedef struct stat64 stat_wrapper_t; |
42 | | #endif |
43 | | #endif // defined(OS_POSIX) |
44 | | |
45 | | // Thin wrapper around an OS-level file. |
46 | | // Note that this class does not provide any support for asynchronous IO, other |
47 | | // than the ability to create asynchronous handles on Windows. |
48 | | // |
49 | | // Note about const: this class does not attempt to determine if the underlying |
50 | | // file system object is affected by a particular method in order to consider |
51 | | // that method const or not. Only methods that deal with member variables in an |
52 | | // obvious non-modifying way are marked as const. Any method that forward calls |
53 | | // to the OS is not considered const, even if there is no apparent change to |
54 | | // member variables. |
55 | | class BUTIL_EXPORT File { |
56 | | MOVE_ONLY_TYPE_FOR_CPP_03(File, RValue) |
57 | | |
58 | | public: |
59 | | // FLAG_(OPEN|CREATE).* are mutually exclusive. You should specify exactly one |
60 | | // of the five (possibly combining with other flags) when opening or creating |
61 | | // a file. |
62 | | // FLAG_(WRITE|APPEND) are mutually exclusive. This is so that APPEND behavior |
63 | | // will be consistent with O_APPEND on POSIX. |
64 | | // FLAG_EXCLUSIVE_(READ|WRITE) only grant exclusive access to the file on |
65 | | // creation on POSIX; for existing files, consider using Lock(). |
66 | | enum Flags { |
67 | | FLAG_OPEN = 1 << 0, // Opens a file, only if it exists. |
68 | | FLAG_CREATE = 1 << 1, // Creates a new file, only if it does not |
69 | | // already exist. |
70 | | FLAG_OPEN_ALWAYS = 1 << 2, // May create a new file. |
71 | | FLAG_CREATE_ALWAYS = 1 << 3, // May overwrite an old file. |
72 | | FLAG_OPEN_TRUNCATED = 1 << 4, // Opens a file and truncates it, only if it |
73 | | // exists. |
74 | | FLAG_READ = 1 << 5, |
75 | | FLAG_WRITE = 1 << 6, |
76 | | FLAG_APPEND = 1 << 7, |
77 | | FLAG_EXCLUSIVE_READ = 1 << 8, // EXCLUSIVE is opposite of Windows SHARE. |
78 | | FLAG_EXCLUSIVE_WRITE = 1 << 9, |
79 | | FLAG_ASYNC = 1 << 10, |
80 | | FLAG_TEMPORARY = 1 << 11, // Used on Windows only. |
81 | | FLAG_HIDDEN = 1 << 12, // Used on Windows only. |
82 | | FLAG_DELETE_ON_CLOSE = 1 << 13, |
83 | | FLAG_WRITE_ATTRIBUTES = 1 << 14, // Used on Windows only. |
84 | | FLAG_SHARE_DELETE = 1 << 15, // Used on Windows only. |
85 | | FLAG_TERMINAL_DEVICE = 1 << 16, // Serial port flags. |
86 | | FLAG_BACKUP_SEMANTICS = 1 << 17, // Used on Windows only. |
87 | | FLAG_EXECUTE = 1 << 18, // Used on Windows only. |
88 | | }; |
89 | | |
90 | | // This enum has been recorded in multiple histograms. If the order of the |
91 | | // fields needs to change, please ensure that those histograms are obsolete or |
92 | | // have been moved to a different enum. |
93 | | // |
94 | | // FILE_ERROR_ACCESS_DENIED is returned when a call fails because of a |
95 | | // filesystem restriction. FILE_ERROR_SECURITY is returned when a browser |
96 | | // policy doesn't allow the operation to be executed. |
97 | | enum Error { |
98 | | FILE_OK = 0, |
99 | | FILE_ERROR_FAILED = -1, |
100 | | FILE_ERROR_IN_USE = -2, |
101 | | FILE_ERROR_EXISTS = -3, |
102 | | FILE_ERROR_NOT_FOUND = -4, |
103 | | FILE_ERROR_ACCESS_DENIED = -5, |
104 | | FILE_ERROR_TOO_MANY_OPENED = -6, |
105 | | FILE_ERROR_NO_MEMORY = -7, |
106 | | FILE_ERROR_NO_SPACE = -8, |
107 | | FILE_ERROR_NOT_A_DIRECTORY = -9, |
108 | | FILE_ERROR_INVALID_OPERATION = -10, |
109 | | FILE_ERROR_SECURITY = -11, |
110 | | FILE_ERROR_ABORT = -12, |
111 | | FILE_ERROR_NOT_A_FILE = -13, |
112 | | FILE_ERROR_NOT_EMPTY = -14, |
113 | | FILE_ERROR_INVALID_URL = -15, |
114 | | FILE_ERROR_IO = -16, |
115 | | // Put new entries here and increment FILE_ERROR_MAX. |
116 | | FILE_ERROR_MAX = -17 |
117 | | }; |
118 | | |
119 | | // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. |
120 | | enum Whence { |
121 | | FROM_BEGIN = 0, |
122 | | FROM_CURRENT = 1, |
123 | | FROM_END = 2 |
124 | | }; |
125 | | |
126 | | // Used to hold information about a given file. |
127 | | // If you add more fields to this structure (platform-specific fields are OK), |
128 | | // make sure to update all functions that use it in file_util_{win|posix}.cc |
129 | | // too, and the ParamTraits<butil::PlatformFileInfo> implementation in |
130 | | // chrome/common/common_param_traits.cc. |
131 | | struct BUTIL_EXPORT Info { |
132 | | Info(); |
133 | | ~Info(); |
134 | | #if defined(OS_POSIX) |
135 | | // Fills this struct with values from |stat_info|. |
136 | | void FromStat(const stat_wrapper_t& stat_info); |
137 | | #endif |
138 | | |
139 | | // The size of the file in bytes. Undefined when is_directory is true. |
140 | | int64_t size; |
141 | | |
142 | | // True if the file corresponds to a directory. |
143 | | bool is_directory; |
144 | | |
145 | | // True if the file corresponds to a symbolic link. |
146 | | bool is_symbolic_link; |
147 | | |
148 | | // The last modified time of a file. |
149 | | butil::Time last_modified; |
150 | | |
151 | | // The last accessed time of a file. |
152 | | butil::Time last_accessed; |
153 | | |
154 | | // The creation time of a file. |
155 | | butil::Time creation_time; |
156 | | }; |
157 | | |
158 | | File(); |
159 | | |
160 | | // Creates or opens the given file. This will fail with 'access denied' if the |
161 | | // |name| contains path traversal ('..') components. |
162 | | File(const FilePath& name, uint32_t flags); |
163 | | |
164 | | // Takes ownership of |platform_file|. |
165 | | explicit File(PlatformFile platform_file); |
166 | | |
167 | | // Creates an object with a specific error_details code. |
168 | | explicit File(Error error_details); |
169 | | |
170 | | // Move constructor for C++03 move emulation of this type. |
171 | | File(RValue other); |
172 | | |
173 | | ~File(); |
174 | | |
175 | | // Move operator= for C++03 move emulation of this type. |
176 | | File& operator=(RValue other); |
177 | | |
178 | | // Creates or opens the given file. |
179 | | void Initialize(const FilePath& name, uint32_t flags); |
180 | | |
181 | | // Creates or opens the given file, allowing paths with traversal ('..') |
182 | | // components. Use only with extreme care. |
183 | | void InitializeUnsafe(const FilePath& name, uint32_t flags); |
184 | | |
185 | | bool IsValid() const; |
186 | | |
187 | | // Returns true if a new file was created (or an old one truncated to zero |
188 | | // length to simulate a new file, which can happen with |
189 | | // FLAG_CREATE_ALWAYS), and false otherwise. |
190 | 0 | bool created() const { return created_; } |
191 | | |
192 | | // Returns the OS result of opening this file. Note that the way to verify |
193 | | // the success of the operation is to use IsValid(), not this method: |
194 | | // File file(name, flags); |
195 | | // if (!file.IsValid()) |
196 | | // return; |
197 | 0 | Error error_details() const { return error_details_; } |
198 | | |
199 | | PlatformFile GetPlatformFile() const; |
200 | | PlatformFile TakePlatformFile(); |
201 | | |
202 | | // Destroying this object closes the file automatically. |
203 | | void Close(); |
204 | | |
205 | | // Changes current position in the file to an |offset| relative to an origin |
206 | | // defined by |whence|. Returns the resultant current position in the file |
207 | | // (relative to the start) or -1 in case of error. |
208 | | int64_t Seek(Whence whence, int64_t offset); |
209 | | |
210 | | // Reads the given number of bytes (or until EOF is reached) starting with the |
211 | | // given offset. Returns the number of bytes read, or -1 on error. Note that |
212 | | // this function makes a best effort to read all data on all platforms, so it |
213 | | // is not intended for stream oriented files but instead for cases when the |
214 | | // normal expectation is that actually |size| bytes are read unless there is |
215 | | // an error. |
216 | | int Read(int64_t offset, char* data, int size); |
217 | | |
218 | | // Same as above but without seek. |
219 | | int ReadAtCurrentPos(char* data, int size); |
220 | | |
221 | | // Reads the given number of bytes (or until EOF is reached) starting with the |
222 | | // given offset, but does not make any effort to read all data on all |
223 | | // platforms. Returns the number of bytes read, or -1 on error. |
224 | | int ReadNoBestEffort(int64_t offset, char* data, int size); |
225 | | |
226 | | // Same as above but without seek. |
227 | | int ReadAtCurrentPosNoBestEffort(char* data, int size); |
228 | | |
229 | | // Writes the given buffer into the file at the given offset, overwritting any |
230 | | // data that was previously there. Returns the number of bytes written, or -1 |
231 | | // on error. Note that this function makes a best effort to write all data on |
232 | | // all platforms. |
233 | | // Ignores the offset and writes to the end of the file if the file was opened |
234 | | // with FLAG_APPEND. |
235 | | int Write(int64_t offset, const char* data, int size); |
236 | | |
237 | | // Save as above but without seek. |
238 | | int WriteAtCurrentPos(const char* data, int size); |
239 | | |
240 | | // Save as above but does not make any effort to write all data on all |
241 | | // platforms. Returns the number of bytes written, or -1 on error. |
242 | | int WriteAtCurrentPosNoBestEffort(const char* data, int size); |
243 | | |
244 | | // Returns the current size of this file, or a negative number on failure. |
245 | | int64_t GetLength(); |
246 | | |
247 | | // Truncates the file to the given length. If |length| is greater than the |
248 | | // current size of the file, the file is extended with zeros. If the file |
249 | | // doesn't exist, |false| is returned. |
250 | | bool SetLength(int64_t length); |
251 | | |
252 | | // Flushes the buffers. |
253 | | bool Flush(); |
254 | | |
255 | | // Updates the file times. |
256 | | bool SetTimes(Time last_access_time, Time last_modified_time); |
257 | | |
258 | | // Returns some basic information for the given file. |
259 | | bool GetInfo(Info* info); |
260 | | |
261 | | // Attempts to take an exclusive write lock on the file. Returns immediately |
262 | | // (i.e. does not wait for another process to unlock the file). If the lock |
263 | | // was obtained, the result will be FILE_OK. A lock only guarantees |
264 | | // that other processes may not also take a lock on the same file with the |
265 | | // same API - it may still be opened, renamed, unlinked, etc. |
266 | | // |
267 | | // Common semantics: |
268 | | // * Locks are held by processes, but not inherited by child processes. |
269 | | // * Locks are released by the OS on file close or process termination. |
270 | | // * Locks are reliable only on local filesystems. |
271 | | // * Duplicated file handles may also write to locked files. |
272 | | // Windows-specific semantics: |
273 | | // * Locks are mandatory for read/write APIs, advisory for mapping APIs. |
274 | | // * Within a process, locking the same file (by the same or new handle) |
275 | | // will fail. |
276 | | // POSIX-specific semantics: |
277 | | // * Locks are advisory only. |
278 | | // * Within a process, locking the same file (by the same or new handle) |
279 | | // will succeed. |
280 | | // * Closing any descriptor on a given file releases the lock. |
281 | | Error Lock(); |
282 | | |
283 | | // Unlock a file previously locked. |
284 | | Error Unlock(); |
285 | | |
286 | 0 | bool async() const { return async_; } |
287 | | |
288 | | #if defined(OS_WIN) |
289 | | static Error OSErrorToFileError(DWORD last_error); |
290 | | #elif defined(OS_POSIX) |
291 | | static Error OSErrorToFileError(int saved_errno); |
292 | | #endif |
293 | | |
294 | | // Converts an error value to a human-readable form. Used for logging. |
295 | | static std::string ErrorToString(Error error); |
296 | | |
297 | | private: |
298 | | void SetPlatformFile(PlatformFile file); |
299 | | |
300 | | #if defined(OS_WIN) |
301 | | win::ScopedHandle file_; |
302 | | #elif defined(OS_POSIX) |
303 | | ScopedFD file_; |
304 | | #endif |
305 | | |
306 | | Error error_details_; |
307 | | bool created_; |
308 | | bool async_; |
309 | | }; |
310 | | |
311 | | } // namespace butil |
312 | | |
313 | | #endif // BUTIL_FILES_FILE_H_ |