Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #ifndef BASE_PLATFORM_FILE_H_ |
michael@0 | 6 | #define BASE_PLATFORM_FILE_H_ |
michael@0 | 7 | |
michael@0 | 8 | #include "build/build_config.h" |
michael@0 | 9 | #if defined(OS_WIN) |
michael@0 | 10 | #include <windows.h> |
michael@0 | 11 | #endif |
michael@0 | 12 | |
michael@0 | 13 | #include <string> |
michael@0 | 14 | |
michael@0 | 15 | #include "base/base_export.h" |
michael@0 | 16 | #include "base/basictypes.h" |
michael@0 | 17 | #include "base/files/file_path.h" |
michael@0 | 18 | #include "base/time/time.h" |
michael@0 | 19 | |
michael@0 | 20 | namespace base { |
michael@0 | 21 | |
michael@0 | 22 | // PLATFORM_FILE_(OPEN|CREATE).* are mutually exclusive. You should specify |
michael@0 | 23 | // exactly one of the five (possibly combining with other flags) when opening |
michael@0 | 24 | // or creating a file. |
michael@0 | 25 | // PLATFORM_FILE_(WRITE|APPEND) are mutually exclusive. This is so that APPEND |
michael@0 | 26 | // behavior will be consistent with O_APPEND on POSIX. |
michael@0 | 27 | enum PlatformFileFlags { |
michael@0 | 28 | PLATFORM_FILE_OPEN = 1 << 0, // Opens a file, only if it exists. |
michael@0 | 29 | PLATFORM_FILE_CREATE = 1 << 1, // Creates a new file, only if it |
michael@0 | 30 | // does not already exist. |
michael@0 | 31 | PLATFORM_FILE_OPEN_ALWAYS = 1 << 2, // May create a new file. |
michael@0 | 32 | PLATFORM_FILE_CREATE_ALWAYS = 1 << 3, // May overwrite an old file. |
michael@0 | 33 | PLATFORM_FILE_OPEN_TRUNCATED = 1 << 4, // Opens a file and truncates it, |
michael@0 | 34 | // only if it exists. |
michael@0 | 35 | PLATFORM_FILE_READ = 1 << 5, |
michael@0 | 36 | PLATFORM_FILE_WRITE = 1 << 6, |
michael@0 | 37 | PLATFORM_FILE_APPEND = 1 << 7, |
michael@0 | 38 | PLATFORM_FILE_EXCLUSIVE_READ = 1 << 8, // EXCLUSIVE is opposite of Windows |
michael@0 | 39 | // SHARE |
michael@0 | 40 | PLATFORM_FILE_EXCLUSIVE_WRITE = 1 << 9, |
michael@0 | 41 | PLATFORM_FILE_ASYNC = 1 << 10, |
michael@0 | 42 | PLATFORM_FILE_TEMPORARY = 1 << 11, // Used on Windows only |
michael@0 | 43 | PLATFORM_FILE_HIDDEN = 1 << 12, // Used on Windows only |
michael@0 | 44 | PLATFORM_FILE_DELETE_ON_CLOSE = 1 << 13, |
michael@0 | 45 | |
michael@0 | 46 | PLATFORM_FILE_WRITE_ATTRIBUTES = 1 << 14, // Used on Windows only |
michael@0 | 47 | PLATFORM_FILE_ENUMERATE = 1 << 15, // May enumerate directory |
michael@0 | 48 | |
michael@0 | 49 | PLATFORM_FILE_SHARE_DELETE = 1 << 16, // Used on Windows only |
michael@0 | 50 | |
michael@0 | 51 | PLATFORM_FILE_TERMINAL_DEVICE = 1 << 17, // Serial port flags |
michael@0 | 52 | PLATFORM_FILE_BACKUP_SEMANTICS = 1 << 18, // Used on Windows only |
michael@0 | 53 | |
michael@0 | 54 | PLATFORM_FILE_EXECUTE = 1 << 19, // Used on Windows only |
michael@0 | 55 | }; |
michael@0 | 56 | |
michael@0 | 57 | // PLATFORM_FILE_ERROR_ACCESS_DENIED is returned when a call fails because of |
michael@0 | 58 | // a filesystem restriction. PLATFORM_FILE_ERROR_SECURITY is returned when a |
michael@0 | 59 | // browser policy doesn't allow the operation to be executed. |
michael@0 | 60 | enum PlatformFileError { |
michael@0 | 61 | PLATFORM_FILE_OK = 0, |
michael@0 | 62 | PLATFORM_FILE_ERROR_FAILED = -1, |
michael@0 | 63 | PLATFORM_FILE_ERROR_IN_USE = -2, |
michael@0 | 64 | PLATFORM_FILE_ERROR_EXISTS = -3, |
michael@0 | 65 | PLATFORM_FILE_ERROR_NOT_FOUND = -4, |
michael@0 | 66 | PLATFORM_FILE_ERROR_ACCESS_DENIED = -5, |
michael@0 | 67 | PLATFORM_FILE_ERROR_TOO_MANY_OPENED = -6, |
michael@0 | 68 | PLATFORM_FILE_ERROR_NO_MEMORY = -7, |
michael@0 | 69 | PLATFORM_FILE_ERROR_NO_SPACE = -8, |
michael@0 | 70 | PLATFORM_FILE_ERROR_NOT_A_DIRECTORY = -9, |
michael@0 | 71 | PLATFORM_FILE_ERROR_INVALID_OPERATION = -10, |
michael@0 | 72 | PLATFORM_FILE_ERROR_SECURITY = -11, |
michael@0 | 73 | PLATFORM_FILE_ERROR_ABORT = -12, |
michael@0 | 74 | PLATFORM_FILE_ERROR_NOT_A_FILE = -13, |
michael@0 | 75 | PLATFORM_FILE_ERROR_NOT_EMPTY = -14, |
michael@0 | 76 | PLATFORM_FILE_ERROR_INVALID_URL = -15, |
michael@0 | 77 | PLATFORM_FILE_ERROR_IO = -16, |
michael@0 | 78 | // Put new entries here and increment PLATFORM_FILE_ERROR_MAX. |
michael@0 | 79 | PLATFORM_FILE_ERROR_MAX = -17 |
michael@0 | 80 | }; |
michael@0 | 81 | |
michael@0 | 82 | // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. |
michael@0 | 83 | enum PlatformFileWhence { |
michael@0 | 84 | PLATFORM_FILE_FROM_BEGIN = 0, |
michael@0 | 85 | PLATFORM_FILE_FROM_CURRENT = 1, |
michael@0 | 86 | PLATFORM_FILE_FROM_END = 2 |
michael@0 | 87 | }; |
michael@0 | 88 | |
michael@0 | 89 | // Used to hold information about a given file. |
michael@0 | 90 | // If you add more fields to this structure (platform-specific fields are OK), |
michael@0 | 91 | // make sure to update all functions that use it in file_util_{win|posix}.cc |
michael@0 | 92 | // too, and the ParamTraits<base::PlatformFileInfo> implementation in |
michael@0 | 93 | // chrome/common/common_param_traits.cc. |
michael@0 | 94 | struct BASE_EXPORT PlatformFileInfo { |
michael@0 | 95 | PlatformFileInfo(); |
michael@0 | 96 | ~PlatformFileInfo(); |
michael@0 | 97 | |
michael@0 | 98 | // The size of the file in bytes. Undefined when is_directory is true. |
michael@0 | 99 | int64 size; |
michael@0 | 100 | |
michael@0 | 101 | // True if the file corresponds to a directory. |
michael@0 | 102 | bool is_directory; |
michael@0 | 103 | |
michael@0 | 104 | // True if the file corresponds to a symbolic link. |
michael@0 | 105 | bool is_symbolic_link; |
michael@0 | 106 | |
michael@0 | 107 | // The last modified time of a file. |
michael@0 | 108 | base::Time last_modified; |
michael@0 | 109 | |
michael@0 | 110 | // The last accessed time of a file. |
michael@0 | 111 | base::Time last_accessed; |
michael@0 | 112 | |
michael@0 | 113 | // The creation time of a file. |
michael@0 | 114 | base::Time creation_time; |
michael@0 | 115 | }; |
michael@0 | 116 | |
michael@0 | 117 | #if defined(OS_WIN) |
michael@0 | 118 | typedef HANDLE PlatformFile; |
michael@0 | 119 | const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE; |
michael@0 | 120 | PlatformFileError LastErrorToPlatformFileError(DWORD saved_errno); |
michael@0 | 121 | #elif defined(OS_POSIX) |
michael@0 | 122 | typedef int PlatformFile; |
michael@0 | 123 | const PlatformFile kInvalidPlatformFileValue = -1; |
michael@0 | 124 | PlatformFileError ErrnoToPlatformFileError(int saved_errno); |
michael@0 | 125 | #endif |
michael@0 | 126 | |
michael@0 | 127 | // Creates or opens the given file. If |created| is provided, it will be set to |
michael@0 | 128 | // true if a new file was created [or an old one truncated to zero length to |
michael@0 | 129 | // simulate a new file, which can happen with PLATFORM_FILE_CREATE_ALWAYS], and |
michael@0 | 130 | // false otherwise. |error| can be NULL. |
michael@0 | 131 | // |
michael@0 | 132 | // This function fails with 'access denied' if the |name| contains path |
michael@0 | 133 | // traversal ('..') components. |
michael@0 | 134 | BASE_EXPORT PlatformFile CreatePlatformFile(const FilePath& name, |
michael@0 | 135 | int flags, |
michael@0 | 136 | bool* created, |
michael@0 | 137 | PlatformFileError* error); |
michael@0 | 138 | |
michael@0 | 139 | // Same as CreatePlatformFile but allows paths with traversal (like \..\) |
michael@0 | 140 | // components. Use only with extreme care. |
michael@0 | 141 | BASE_EXPORT PlatformFile CreatePlatformFileUnsafe(const FilePath& name, |
michael@0 | 142 | int flags, |
michael@0 | 143 | bool* created, |
michael@0 | 144 | PlatformFileError* error); |
michael@0 | 145 | |
michael@0 | 146 | BASE_EXPORT FILE* FdopenPlatformFile(PlatformFile file, const char* mode); |
michael@0 | 147 | |
michael@0 | 148 | // Closes a file handle. Returns |true| on success and |false| otherwise. |
michael@0 | 149 | BASE_EXPORT bool ClosePlatformFile(PlatformFile file); |
michael@0 | 150 | |
michael@0 | 151 | // Changes current position in the file to an |offset| relative to an origin |
michael@0 | 152 | // defined by |whence|. Returns the resultant current position in the file |
michael@0 | 153 | // (relative to the start) or -1 in case of error. |
michael@0 | 154 | BASE_EXPORT int64 SeekPlatformFile(PlatformFile file, |
michael@0 | 155 | PlatformFileWhence whence, |
michael@0 | 156 | int64 offset); |
michael@0 | 157 | |
michael@0 | 158 | // Reads the given number of bytes (or until EOF is reached) starting with the |
michael@0 | 159 | // given offset. Returns the number of bytes read, or -1 on error. Note that |
michael@0 | 160 | // this function makes a best effort to read all data on all platforms, so it is |
michael@0 | 161 | // not intended for stream oriented files but instead for cases when the normal |
michael@0 | 162 | // expectation is that actually |size| bytes are read unless there is an error. |
michael@0 | 163 | BASE_EXPORT int ReadPlatformFile(PlatformFile file, int64 offset, |
michael@0 | 164 | char* data, int size); |
michael@0 | 165 | |
michael@0 | 166 | // Same as above but without seek. |
michael@0 | 167 | BASE_EXPORT int ReadPlatformFileAtCurrentPos(PlatformFile file, |
michael@0 | 168 | char* data, int size); |
michael@0 | 169 | |
michael@0 | 170 | // Reads the given number of bytes (or until EOF is reached) starting with the |
michael@0 | 171 | // given offset, but does not make any effort to read all data on all platforms. |
michael@0 | 172 | // Returns the number of bytes read, or -1 on error. |
michael@0 | 173 | BASE_EXPORT int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, |
michael@0 | 174 | char* data, int size); |
michael@0 | 175 | |
michael@0 | 176 | // Same as above but without seek. |
michael@0 | 177 | BASE_EXPORT int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, |
michael@0 | 178 | char* data, int size); |
michael@0 | 179 | |
michael@0 | 180 | // Writes the given buffer into the file at the given offset, overwritting any |
michael@0 | 181 | // data that was previously there. Returns the number of bytes written, or -1 |
michael@0 | 182 | // on error. Note that this function makes a best effort to write all data on |
michael@0 | 183 | // all platforms. |
michael@0 | 184 | // Ignores the offset and writes to the end of the file if the file was opened |
michael@0 | 185 | // with PLATFORM_FILE_APPEND. |
michael@0 | 186 | BASE_EXPORT int WritePlatformFile(PlatformFile file, int64 offset, |
michael@0 | 187 | const char* data, int size); |
michael@0 | 188 | |
michael@0 | 189 | // Save as above but without seek. |
michael@0 | 190 | BASE_EXPORT int WritePlatformFileAtCurrentPos(PlatformFile file, |
michael@0 | 191 | const char* data, int size); |
michael@0 | 192 | |
michael@0 | 193 | // Save as above but does not make any effort to write all data on all |
michael@0 | 194 | // platforms. Returns the number of bytes written, or -1 on error. |
michael@0 | 195 | BASE_EXPORT int WritePlatformFileCurPosNoBestEffort(PlatformFile file, |
michael@0 | 196 | const char* data, int size); |
michael@0 | 197 | |
michael@0 | 198 | // Truncates the given file to the given length. If |length| is greater than |
michael@0 | 199 | // the current size of the file, the file is extended with zeros. If the file |
michael@0 | 200 | // doesn't exist, |false| is returned. |
michael@0 | 201 | BASE_EXPORT bool TruncatePlatformFile(PlatformFile file, int64 length); |
michael@0 | 202 | |
michael@0 | 203 | // Flushes the buffers of the given file. |
michael@0 | 204 | BASE_EXPORT bool FlushPlatformFile(PlatformFile file); |
michael@0 | 205 | |
michael@0 | 206 | // Touches the given file. |
michael@0 | 207 | BASE_EXPORT bool TouchPlatformFile(PlatformFile file, |
michael@0 | 208 | const Time& last_access_time, |
michael@0 | 209 | const Time& last_modified_time); |
michael@0 | 210 | |
michael@0 | 211 | // Returns some information for the given file. |
michael@0 | 212 | BASE_EXPORT bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); |
michael@0 | 213 | |
michael@0 | 214 | // Use this class to pass ownership of a PlatformFile to a receiver that may or |
michael@0 | 215 | // may not want to accept it. This class does not own the storage for the |
michael@0 | 216 | // PlatformFile. |
michael@0 | 217 | // |
michael@0 | 218 | // EXAMPLE: |
michael@0 | 219 | // |
michael@0 | 220 | // void MaybeProcessFile(PassPlatformFile pass_file) { |
michael@0 | 221 | // if (...) { |
michael@0 | 222 | // PlatformFile file = pass_file.ReleaseValue(); |
michael@0 | 223 | // // Now, we are responsible for closing |file|. |
michael@0 | 224 | // } |
michael@0 | 225 | // } |
michael@0 | 226 | // |
michael@0 | 227 | // void OpenAndMaybeProcessFile(const FilePath& path) { |
michael@0 | 228 | // PlatformFile file = CreatePlatformFile(path, ...); |
michael@0 | 229 | // MaybeProcessFile(PassPlatformFile(&file)); |
michael@0 | 230 | // if (file != kInvalidPlatformFileValue) |
michael@0 | 231 | // ClosePlatformFile(file); |
michael@0 | 232 | // } |
michael@0 | 233 | // |
michael@0 | 234 | class BASE_EXPORT PassPlatformFile { |
michael@0 | 235 | public: |
michael@0 | 236 | explicit PassPlatformFile(PlatformFile* value) : value_(value) { |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | // Called to retrieve the PlatformFile stored in this object. The caller |
michael@0 | 240 | // gains ownership of the PlatformFile and is now responsible for closing it. |
michael@0 | 241 | // Any subsequent calls to this method will return an invalid PlatformFile. |
michael@0 | 242 | PlatformFile ReleaseValue() { |
michael@0 | 243 | PlatformFile temp = *value_; |
michael@0 | 244 | *value_ = kInvalidPlatformFileValue; |
michael@0 | 245 | return temp; |
michael@0 | 246 | } |
michael@0 | 247 | |
michael@0 | 248 | private: |
michael@0 | 249 | PlatformFile* value_; |
michael@0 | 250 | }; |
michael@0 | 251 | |
michael@0 | 252 | } // namespace base |
michael@0 | 253 | |
michael@0 | 254 | #endif // BASE_PLATFORM_FILE_H_ |