| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #ifndef CRASHPAD_UTIL_FILE_FILE_IO_H_ |
| 16 #define CRASHPAD_UTIL_FILE_FILE_IO_H_ |
| 17 |
| 18 #include <sys/types.h> |
| 19 |
| 20 #include "build/build_config.h" |
| 21 |
| 22 #if defined(OS_POSIX) |
| 23 #include "base/files/scoped_file.h" |
| 24 #elif defined(OS_WIN) |
| 25 #include <windows.h> |
| 26 #include "util/win/scoped_handle.h" |
| 27 #endif |
| 28 |
| 29 //! \file |
| 30 |
| 31 #if defined(OS_POSIX) || DOXYGEN |
| 32 |
| 33 //! \brief A `PLOG()` macro usable for standard input/output error conditions. |
| 34 //! |
| 35 //! The `PLOG()` macro uses `errno` on POSIX and is appropriate to report |
| 36 //! errors from standard input/output functions. On Windows, `PLOG()` uses |
| 37 //! `GetLastError()`, and cannot be used to report errors from standard |
| 38 //! input/output functions. This macro uses `PLOG()` when appropriate for |
| 39 //! standard I/O functions, and `LOG()` otherwise. |
| 40 #define STDIO_PLOG(x) PLOG(x) |
| 41 |
| 42 #else |
| 43 |
| 44 #define STDIO_PLOG(x) LOG(x) |
| 45 #define fseeko(file, offset, whence) _fseeki64(file, offset, whence) |
| 46 #define ftello(file) _ftelli64(file) |
| 47 |
| 48 #endif |
| 49 |
| 50 namespace base { |
| 51 class FilePath; |
| 52 } // namespace base |
| 53 |
| 54 namespace crashpad { |
| 55 |
| 56 #if defined(OS_POSIX) || DOXYGEN |
| 57 |
| 58 //! \brief Platform-specific alias for a low-level file handle. |
| 59 using FileHandle = int; |
| 60 |
| 61 //! \brief Platform-specific alias for a position in an open file. |
| 62 using FileOffset = off_t; |
| 63 |
| 64 //! \brief Scoped wrapper of a FileHandle. |
| 65 using ScopedFileHandle = base::ScopedFD; |
| 66 |
| 67 //! \brief A value that can never be a valid FileHandle. |
| 68 const FileHandle kInvalidFileHandle = -1; |
| 69 |
| 70 using FileOperationResult = ssize_t; |
| 71 |
| 72 #elif defined(OS_WIN) |
| 73 |
| 74 using FileHandle = HANDLE; |
| 75 using FileOffset = LONGLONG; |
| 76 using ScopedFileHandle = ScopedFileHANDLE; |
| 77 using FileOperationResult = LONG_PTR; |
| 78 |
| 79 const FileHandle kInvalidFileHandle = INVALID_HANDLE_VALUE; |
| 80 |
| 81 #endif |
| 82 |
| 83 //! \brief Determines the mode that LoggingOpenFileForWrite() uses. |
| 84 enum class FileWriteMode { |
| 85 //! \brief Opens the file if it exists, or fails if it does not. |
| 86 kReuseOrFail, |
| 87 |
| 88 //! \brief Opens the file if it exists, or creates a new file. |
| 89 kReuseOrCreate, |
| 90 |
| 91 //! \brief Creates a new file. If the file already exists, it will be |
| 92 //! overwritten. |
| 93 kTruncateOrCreate, |
| 94 |
| 95 //! \brief Creates a new file. If the file already exists, the open will fail. |
| 96 kCreateOrFail, |
| 97 }; |
| 98 |
| 99 //! \brief Determines the permissions bits for files created on POSIX systems. |
| 100 enum class FilePermissions : bool { |
| 101 //! \brief Equivalent to `0600`. |
| 102 kOwnerOnly, |
| 103 |
| 104 //! \brief Equivalent to `0644`. |
| 105 kWorldReadable, |
| 106 }; |
| 107 |
| 108 //! \brief Determines the locking mode that LoggingLockFile() uses. |
| 109 enum class FileLocking : bool { |
| 110 //! \brief Equivalent to `flock()` with `LOCK_SH`. |
| 111 kShared, |
| 112 |
| 113 //! \brief Equivalent to `flock()` with `LOCK_EX`. |
| 114 kExclusive, |
| 115 }; |
| 116 |
| 117 //! \brief Reads from a file, retrying when interrupted on POSIX or following a |
| 118 //! short read. |
| 119 //! |
| 120 //! This function reads into \a buffer, stopping only when \a size bytes have |
| 121 //! been read or when end-of-file has been reached. On Windows, reading from |
| 122 //! sockets is not currently supported. |
| 123 //! |
| 124 //! \return The number of bytes read and placed into \a buffer, or `-1` on |
| 125 //! error, with `errno` or `GetLastError()` set appropriately. On error, a |
| 126 //! portion of \a file may have been read into \a buffer. |
| 127 //! |
| 128 //! \sa WriteFile |
| 129 //! \sa LoggingReadFile |
| 130 //! \sa CheckedReadFile |
| 131 //! \sa CheckedReadFileAtEOF |
| 132 FileOperationResult ReadFile(FileHandle file, void* buffer, size_t size); |
| 133 |
| 134 //! \brief Writes to a file, retrying when interrupted or following a short |
| 135 //! write on POSIX. |
| 136 //! |
| 137 //! This function writes to \a file, stopping only when \a size bytes have been |
| 138 //! written. |
| 139 //! |
| 140 //! \return The number of bytes written from \a buffer, or `-1` on error, with |
| 141 //! `errno` or `GetLastError()` set appropriately. On error, a portion of |
| 142 //! \a buffer may have been written to \a file. |
| 143 //! |
| 144 //! \sa ReadFile |
| 145 //! \sa LoggingWriteFile |
| 146 //! \sa CheckedWriteFile |
| 147 FileOperationResult WriteFile(FileHandle file, const void* buffer, size_t size); |
| 148 |
| 149 //! \brief Wraps ReadFile(), ensuring that exactly \a size bytes are read. |
| 150 //! |
| 151 //! \return `true` on success. If \a size is out of the range of possible |
| 152 //! ReadFile() return values, if the underlying ReadFile() fails, or if |
| 153 //! other than \a size bytes were read, this function logs a message and |
| 154 //! returns `false`. |
| 155 //! |
| 156 //! \sa LoggingWriteFile |
| 157 //! \sa ReadFile |
| 158 //! \sa CheckedReadFile |
| 159 //! \sa CheckedReadFileAtEOF |
| 160 bool LoggingReadFile(FileHandle file, void* buffer, size_t size); |
| 161 |
| 162 //! \brief Wraps WriteFile(), ensuring that exactly \a size bytes are written. |
| 163 //! |
| 164 //! \return `true` on success. If \a size is out of the range of possible |
| 165 //! WriteFile() return values, if the underlying WriteFile() fails, or if |
| 166 //! other than \a size bytes were written, this function logs a message and |
| 167 //! returns `false`. |
| 168 //! |
| 169 //! \sa LoggingReadFile |
| 170 //! \sa WriteFile |
| 171 //! \sa CheckedWriteFile |
| 172 bool LoggingWriteFile(FileHandle file, const void* buffer, size_t size); |
| 173 |
| 174 //! \brief Wraps ReadFile(), ensuring that exactly \a size bytes are read. |
| 175 //! |
| 176 //! If \a size is out of the range of possible ReadFile() return values, if the |
| 177 //! underlying ReadFile() fails, or if other than \a size bytes were read, this |
| 178 //! function causes execution to terminate without returning. |
| 179 //! |
| 180 //! \sa CheckedWriteFile |
| 181 //! \sa ReadFile |
| 182 //! \sa LoggingReadFile |
| 183 //! \sa CheckedReadFileAtEOF |
| 184 void CheckedReadFile(FileHandle file, void* buffer, size_t size); |
| 185 |
| 186 //! \brief Wraps WriteFile(), ensuring that exactly \a size bytes are written. |
| 187 //! |
| 188 //! If \a size is out of the range of possible WriteFile() return values, if the |
| 189 //! underlying WriteFile() fails, or if other than \a size bytes were written, |
| 190 //! this function causes execution to terminate without returning. |
| 191 //! |
| 192 //! \sa CheckedReadFile |
| 193 //! \sa WriteFile |
| 194 //! \sa LoggingWriteFile |
| 195 void CheckedWriteFile(FileHandle file, const void* buffer, size_t size); |
| 196 |
| 197 //! \brief Wraps ReadFile(), ensuring that it indicates end-of-file. |
| 198 //! |
| 199 //! Attempts to read a single byte from \a file, expecting no data to be read. |
| 200 //! If the underlying ReadFile() fails, or if a byte actually is read, this |
| 201 //! function causes execution to terminate without returning. |
| 202 //! |
| 203 //! \sa CheckedReadFile |
| 204 //! \sa ReadFile |
| 205 void CheckedReadFileAtEOF(FileHandle file); |
| 206 |
| 207 //! \brief Wraps `open()` or `CreateFile()`, opening an existing file for |
| 208 //! reading. |
| 209 //! |
| 210 //! \return The newly opened FileHandle, or an invalid FileHandle on failure. |
| 211 //! |
| 212 //! \sa ScopedFileHandle |
| 213 //! \sa OpenFileForWrite |
| 214 //! \sa OpenFileForReadAndWrite |
| 215 //! \sa LoggingOpenFileForRead |
| 216 FileHandle OpenFileForRead(const base::FilePath& path); |
| 217 |
| 218 //! \brief Wraps `open()` or `CreateFile()`, creating a file for output. |
| 219 //! |
| 220 //! \a mode determines the style (truncate, reuse, etc.) that is used to open |
| 221 //! the file. On POSIX, \a permissions determines the value that is passed as |
| 222 //! `mode` to `open()`. On Windows, the file is always opened in binary mode |
| 223 //! (that is, no CRLF translation). On Windows, the file is opened for sharing, |
| 224 //! see LoggingLockFile() and LoggingUnlockFile() to control concurrent access. |
| 225 //! |
| 226 //! \return The newly opened FileHandle, or an invalid FileHandle on failure. |
| 227 //! |
| 228 //! \sa ScopedFileHandle |
| 229 //! \sa OpenFileForRead |
| 230 //! \sa OpenFileForReadAndWrite |
| 231 //! \sa LoggingOpenFileForWrite |
| 232 FileHandle OpenFileForWrite(const base::FilePath& path, |
| 233 FileWriteMode mode, |
| 234 FilePermissions permissions); |
| 235 |
| 236 //! \brief Wraps `open()` or `CreateFile()`, creating a file for both input and |
| 237 //! output. |
| 238 //! |
| 239 //! \a mode determines the style (truncate, reuse, etc.) that is used to open |
| 240 //! the file. On POSIX, \a permissions determines the value that is passed as |
| 241 //! `mode` to `open()`. On Windows, the file is always opened in binary mode |
| 242 //! (that is, no CRLF translation). On Windows, the file is opened for sharing, |
| 243 //! see LoggingLockFile() and LoggingUnlockFile() to control concurrent access. |
| 244 //! |
| 245 //! \return The newly opened FileHandle, or an invalid FileHandle on failure. |
| 246 //! |
| 247 //! \sa ScopedFileHandle |
| 248 //! \sa OpenFileForRead |
| 249 //! \sa OpenFileForWrite |
| 250 //! \sa LoggingOpenFileForReadAndWrite |
| 251 FileHandle OpenFileForReadAndWrite(const base::FilePath& path, |
| 252 FileWriteMode mode, |
| 253 FilePermissions permissions); |
| 254 |
| 255 //! \brief Wraps OpenFileForRead(), logging an error if the operation fails. |
| 256 //! |
| 257 //! \return The newly opened FileHandle, or an invalid FileHandle on failure. |
| 258 //! |
| 259 //! \sa ScopedFileHandle |
| 260 //! \sa LoggingOpenFileForWrite |
| 261 //! \sa LoggingOpenFileForReadAndWrite |
| 262 FileHandle LoggingOpenFileForRead(const base::FilePath& path); |
| 263 |
| 264 //! \brief Wraps OpenFileForWrite(), logging an error if the operation fails. |
| 265 //! |
| 266 //! \return The newly opened FileHandle, or an invalid FileHandle on failure. |
| 267 //! |
| 268 //! \sa ScopedFileHandle |
| 269 //! \sa LoggingOpenFileForRead |
| 270 //! \sa LoggingOpenFileForReadAndWrite |
| 271 FileHandle LoggingOpenFileForWrite(const base::FilePath& path, |
| 272 FileWriteMode mode, |
| 273 FilePermissions permissions); |
| 274 |
| 275 //! \brief Wraps OpenFileForReadAndWrite(), logging an error if the operation |
| 276 //! fails. |
| 277 //! |
| 278 //! \return The newly opened FileHandle, or an invalid FileHandle on failure. |
| 279 //! |
| 280 //! \sa ScopedFileHandle |
| 281 //! \sa LoggingOpenFileForRead |
| 282 //! \sa LoggingOpenFileForWrite |
| 283 FileHandle LoggingOpenFileForReadAndWrite(const base::FilePath& path, |
| 284 FileWriteMode mode, |
| 285 FilePermissions permissions); |
| 286 |
| 287 //! \brief Locks the given \a file using `flock()` on POSIX or `LockFileEx()` on |
| 288 //! Windows. |
| 289 //! |
| 290 //! It is an error to attempt to lock a file in a different mode when it is |
| 291 //! already locked. This call will block until the lock is acquired. The |
| 292 //! entire file is locked. |
| 293 //! |
| 294 //! If \a locking is FileLocking::kShared, \a file must have been opened for |
| 295 //! reading, and if it's FileLocking::kExclusive, \a file must have been opened |
| 296 //! for writing. |
| 297 //! |
| 298 //! \param[in] file The open file handle to be locked. |
| 299 //! \param[in] locking Controls whether the lock is a shared reader lock, or an |
| 300 //! exclusive writer lock. |
| 301 //! |
| 302 //! \return `true` on success, or `false` and a message will be logged. |
| 303 bool LoggingLockFile(FileHandle file, FileLocking locking); |
| 304 |
| 305 //! \brief Unlocks a file previously locked with LoggingLockFile(). |
| 306 //! |
| 307 //! It is an error to attempt to unlock a file that was not previously locked. |
| 308 //! A previously-locked file should be unlocked before closing the file handle, |
| 309 //! otherwise on some OSs the lock may not be released immediately. |
| 310 //! |
| 311 //! \param[in] file The open locked file handle to be unlocked. |
| 312 //! |
| 313 //! \return `true` on success, or `false` and a message will be logged. |
| 314 bool LoggingUnlockFile(FileHandle file); |
| 315 |
| 316 //! \brief Wraps `lseek()` or `SetFilePointerEx()`. Logs an error if the |
| 317 //! operation fails. |
| 318 //! |
| 319 //! Repositions the offset of the open \a file to the specified \a offset, |
| 320 //! relative to \a whence. \a whence must be one of `SEEK_SET`, `SEEK_CUR`, or |
| 321 //! `SEEK_END`, and is interpreted in the usual way. |
| 322 //! |
| 323 //! \return The resulting offset in bytes from the beginning of the file, or |
| 324 //! `-1` on failure. |
| 325 FileOffset LoggingSeekFile(FileHandle file, FileOffset offset, int whence); |
| 326 |
| 327 //! \brief Truncates the given \a file to zero bytes in length. |
| 328 //! |
| 329 //! \return `true` on success, or `false`, and a message will be logged. |
| 330 bool LoggingTruncateFile(FileHandle file); |
| 331 |
| 332 //! \brief Wraps `close()` or `CloseHandle()`, logging an error if the operation |
| 333 //! fails. |
| 334 //! |
| 335 //! \return On success, `true` is returned. On failure, an error is logged and |
| 336 //! `false` is returned. |
| 337 bool LoggingCloseFile(FileHandle file); |
| 338 |
| 339 //! \brief Wraps `close()` or `CloseHandle()`, ensuring that it succeeds. |
| 340 //! |
| 341 //! If the underlying function fails, this function causes execution to |
| 342 //! terminate without returning. |
| 343 void CheckedCloseFile(FileHandle file); |
| 344 |
| 345 } // namespace crashpad |
| 346 |
| 347 #endif // CRASHPAD_UTIL_FILE_FILE_IO_H_ |
| OLD | NEW |