michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_PLATFORM_FILE_H_ michael@0: #define BASE_PLATFORM_FILE_H_ michael@0: michael@0: #include "build/build_config.h" michael@0: #if defined(OS_WIN) michael@0: #include michael@0: #endif michael@0: michael@0: #include michael@0: michael@0: #include "base/base_export.h" michael@0: #include "base/basictypes.h" michael@0: #include "base/files/file_path.h" michael@0: #include "base/time/time.h" michael@0: michael@0: namespace base { michael@0: michael@0: // PLATFORM_FILE_(OPEN|CREATE).* are mutually exclusive. You should specify michael@0: // exactly one of the five (possibly combining with other flags) when opening michael@0: // or creating a file. michael@0: // PLATFORM_FILE_(WRITE|APPEND) are mutually exclusive. This is so that APPEND michael@0: // behavior will be consistent with O_APPEND on POSIX. michael@0: enum PlatformFileFlags { michael@0: PLATFORM_FILE_OPEN = 1 << 0, // Opens a file, only if it exists. michael@0: PLATFORM_FILE_CREATE = 1 << 1, // Creates a new file, only if it michael@0: // does not already exist. michael@0: PLATFORM_FILE_OPEN_ALWAYS = 1 << 2, // May create a new file. michael@0: PLATFORM_FILE_CREATE_ALWAYS = 1 << 3, // May overwrite an old file. michael@0: PLATFORM_FILE_OPEN_TRUNCATED = 1 << 4, // Opens a file and truncates it, michael@0: // only if it exists. michael@0: PLATFORM_FILE_READ = 1 << 5, michael@0: PLATFORM_FILE_WRITE = 1 << 6, michael@0: PLATFORM_FILE_APPEND = 1 << 7, michael@0: PLATFORM_FILE_EXCLUSIVE_READ = 1 << 8, // EXCLUSIVE is opposite of Windows michael@0: // SHARE michael@0: PLATFORM_FILE_EXCLUSIVE_WRITE = 1 << 9, michael@0: PLATFORM_FILE_ASYNC = 1 << 10, michael@0: PLATFORM_FILE_TEMPORARY = 1 << 11, // Used on Windows only michael@0: PLATFORM_FILE_HIDDEN = 1 << 12, // Used on Windows only michael@0: PLATFORM_FILE_DELETE_ON_CLOSE = 1 << 13, michael@0: michael@0: PLATFORM_FILE_WRITE_ATTRIBUTES = 1 << 14, // Used on Windows only michael@0: PLATFORM_FILE_ENUMERATE = 1 << 15, // May enumerate directory michael@0: michael@0: PLATFORM_FILE_SHARE_DELETE = 1 << 16, // Used on Windows only michael@0: michael@0: PLATFORM_FILE_TERMINAL_DEVICE = 1 << 17, // Serial port flags michael@0: PLATFORM_FILE_BACKUP_SEMANTICS = 1 << 18, // Used on Windows only michael@0: michael@0: PLATFORM_FILE_EXECUTE = 1 << 19, // Used on Windows only michael@0: }; michael@0: michael@0: // PLATFORM_FILE_ERROR_ACCESS_DENIED is returned when a call fails because of michael@0: // a filesystem restriction. PLATFORM_FILE_ERROR_SECURITY is returned when a michael@0: // browser policy doesn't allow the operation to be executed. michael@0: enum PlatformFileError { michael@0: PLATFORM_FILE_OK = 0, michael@0: PLATFORM_FILE_ERROR_FAILED = -1, michael@0: PLATFORM_FILE_ERROR_IN_USE = -2, michael@0: PLATFORM_FILE_ERROR_EXISTS = -3, michael@0: PLATFORM_FILE_ERROR_NOT_FOUND = -4, michael@0: PLATFORM_FILE_ERROR_ACCESS_DENIED = -5, michael@0: PLATFORM_FILE_ERROR_TOO_MANY_OPENED = -6, michael@0: PLATFORM_FILE_ERROR_NO_MEMORY = -7, michael@0: PLATFORM_FILE_ERROR_NO_SPACE = -8, michael@0: PLATFORM_FILE_ERROR_NOT_A_DIRECTORY = -9, michael@0: PLATFORM_FILE_ERROR_INVALID_OPERATION = -10, michael@0: PLATFORM_FILE_ERROR_SECURITY = -11, michael@0: PLATFORM_FILE_ERROR_ABORT = -12, michael@0: PLATFORM_FILE_ERROR_NOT_A_FILE = -13, michael@0: PLATFORM_FILE_ERROR_NOT_EMPTY = -14, michael@0: PLATFORM_FILE_ERROR_INVALID_URL = -15, michael@0: PLATFORM_FILE_ERROR_IO = -16, michael@0: // Put new entries here and increment PLATFORM_FILE_ERROR_MAX. michael@0: PLATFORM_FILE_ERROR_MAX = -17 michael@0: }; michael@0: michael@0: // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. michael@0: enum PlatformFileWhence { michael@0: PLATFORM_FILE_FROM_BEGIN = 0, michael@0: PLATFORM_FILE_FROM_CURRENT = 1, michael@0: PLATFORM_FILE_FROM_END = 2 michael@0: }; michael@0: michael@0: // Used to hold information about a given file. michael@0: // If you add more fields to this structure (platform-specific fields are OK), michael@0: // make sure to update all functions that use it in file_util_{win|posix}.cc michael@0: // too, and the ParamTraits implementation in michael@0: // chrome/common/common_param_traits.cc. michael@0: struct BASE_EXPORT PlatformFileInfo { michael@0: PlatformFileInfo(); michael@0: ~PlatformFileInfo(); michael@0: michael@0: // The size of the file in bytes. Undefined when is_directory is true. michael@0: int64 size; michael@0: michael@0: // True if the file corresponds to a directory. michael@0: bool is_directory; michael@0: michael@0: // True if the file corresponds to a symbolic link. michael@0: bool is_symbolic_link; michael@0: michael@0: // The last modified time of a file. michael@0: base::Time last_modified; michael@0: michael@0: // The last accessed time of a file. michael@0: base::Time last_accessed; michael@0: michael@0: // The creation time of a file. michael@0: base::Time creation_time; michael@0: }; michael@0: michael@0: #if defined(OS_WIN) michael@0: typedef HANDLE PlatformFile; michael@0: const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE; michael@0: PlatformFileError LastErrorToPlatformFileError(DWORD saved_errno); michael@0: #elif defined(OS_POSIX) michael@0: typedef int PlatformFile; michael@0: const PlatformFile kInvalidPlatformFileValue = -1; michael@0: PlatformFileError ErrnoToPlatformFileError(int saved_errno); michael@0: #endif michael@0: michael@0: // Creates or opens the given file. If |created| is provided, it will be set to michael@0: // true if a new file was created [or an old one truncated to zero length to michael@0: // simulate a new file, which can happen with PLATFORM_FILE_CREATE_ALWAYS], and michael@0: // false otherwise. |error| can be NULL. michael@0: // michael@0: // This function fails with 'access denied' if the |name| contains path michael@0: // traversal ('..') components. michael@0: BASE_EXPORT PlatformFile CreatePlatformFile(const FilePath& name, michael@0: int flags, michael@0: bool* created, michael@0: PlatformFileError* error); michael@0: michael@0: // Same as CreatePlatformFile but allows paths with traversal (like \..\) michael@0: // components. Use only with extreme care. michael@0: BASE_EXPORT PlatformFile CreatePlatformFileUnsafe(const FilePath& name, michael@0: int flags, michael@0: bool* created, michael@0: PlatformFileError* error); michael@0: michael@0: BASE_EXPORT FILE* FdopenPlatformFile(PlatformFile file, const char* mode); michael@0: michael@0: // Closes a file handle. Returns |true| on success and |false| otherwise. michael@0: BASE_EXPORT bool ClosePlatformFile(PlatformFile file); michael@0: michael@0: // Changes current position in the file to an |offset| relative to an origin michael@0: // defined by |whence|. Returns the resultant current position in the file michael@0: // (relative to the start) or -1 in case of error. michael@0: BASE_EXPORT int64 SeekPlatformFile(PlatformFile file, michael@0: PlatformFileWhence whence, michael@0: int64 offset); michael@0: michael@0: // Reads the given number of bytes (or until EOF is reached) starting with the michael@0: // given offset. Returns the number of bytes read, or -1 on error. Note that michael@0: // this function makes a best effort to read all data on all platforms, so it is michael@0: // not intended for stream oriented files but instead for cases when the normal michael@0: // expectation is that actually |size| bytes are read unless there is an error. michael@0: BASE_EXPORT int ReadPlatformFile(PlatformFile file, int64 offset, michael@0: char* data, int size); michael@0: michael@0: // Same as above but without seek. michael@0: BASE_EXPORT int ReadPlatformFileAtCurrentPos(PlatformFile file, michael@0: char* data, int size); michael@0: michael@0: // Reads the given number of bytes (or until EOF is reached) starting with the michael@0: // given offset, but does not make any effort to read all data on all platforms. michael@0: // Returns the number of bytes read, or -1 on error. michael@0: BASE_EXPORT int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, michael@0: char* data, int size); michael@0: michael@0: // Same as above but without seek. michael@0: BASE_EXPORT int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, michael@0: char* data, int size); michael@0: michael@0: // Writes the given buffer into the file at the given offset, overwritting any michael@0: // data that was previously there. Returns the number of bytes written, or -1 michael@0: // on error. Note that this function makes a best effort to write all data on michael@0: // all platforms. michael@0: // Ignores the offset and writes to the end of the file if the file was opened michael@0: // with PLATFORM_FILE_APPEND. michael@0: BASE_EXPORT int WritePlatformFile(PlatformFile file, int64 offset, michael@0: const char* data, int size); michael@0: michael@0: // Save as above but without seek. michael@0: BASE_EXPORT int WritePlatformFileAtCurrentPos(PlatformFile file, michael@0: const char* data, int size); michael@0: michael@0: // Save as above but does not make any effort to write all data on all michael@0: // platforms. Returns the number of bytes written, or -1 on error. michael@0: BASE_EXPORT int WritePlatformFileCurPosNoBestEffort(PlatformFile file, michael@0: const char* data, int size); michael@0: michael@0: // Truncates the given file to the given length. If |length| is greater than michael@0: // the current size of the file, the file is extended with zeros. If the file michael@0: // doesn't exist, |false| is returned. michael@0: BASE_EXPORT bool TruncatePlatformFile(PlatformFile file, int64 length); michael@0: michael@0: // Flushes the buffers of the given file. michael@0: BASE_EXPORT bool FlushPlatformFile(PlatformFile file); michael@0: michael@0: // Touches the given file. michael@0: BASE_EXPORT bool TouchPlatformFile(PlatformFile file, michael@0: const Time& last_access_time, michael@0: const Time& last_modified_time); michael@0: michael@0: // Returns some information for the given file. michael@0: BASE_EXPORT bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); michael@0: michael@0: // Use this class to pass ownership of a PlatformFile to a receiver that may or michael@0: // may not want to accept it. This class does not own the storage for the michael@0: // PlatformFile. michael@0: // michael@0: // EXAMPLE: michael@0: // michael@0: // void MaybeProcessFile(PassPlatformFile pass_file) { michael@0: // if (...) { michael@0: // PlatformFile file = pass_file.ReleaseValue(); michael@0: // // Now, we are responsible for closing |file|. michael@0: // } michael@0: // } michael@0: // michael@0: // void OpenAndMaybeProcessFile(const FilePath& path) { michael@0: // PlatformFile file = CreatePlatformFile(path, ...); michael@0: // MaybeProcessFile(PassPlatformFile(&file)); michael@0: // if (file != kInvalidPlatformFileValue) michael@0: // ClosePlatformFile(file); michael@0: // } michael@0: // michael@0: class BASE_EXPORT PassPlatformFile { michael@0: public: michael@0: explicit PassPlatformFile(PlatformFile* value) : value_(value) { michael@0: } michael@0: michael@0: // Called to retrieve the PlatformFile stored in this object. The caller michael@0: // gains ownership of the PlatformFile and is now responsible for closing it. michael@0: // Any subsequent calls to this method will return an invalid PlatformFile. michael@0: PlatformFile ReleaseValue() { michael@0: PlatformFile temp = *value_; michael@0: *value_ = kInvalidPlatformFileValue; michael@0: return temp; michael@0: } michael@0: michael@0: private: michael@0: PlatformFile* value_; michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_PLATFORM_FILE_H_