diff options
author | rvargas@chromium.org <rvargas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 00:46:32 +0000 |
---|---|---|
committer | rvargas@chromium.org <rvargas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 00:46:32 +0000 |
commit | f62ac7d5fc78bf1fa97895912dc6554d699209f7 (patch) | |
tree | a957c45429e5002b38093cfb036a4c897ebf1d32 /base/files | |
parent | 554472eb4d1de8e199b5c48db6f2cf2629267fc6 (diff) | |
download | chromium_src-f62ac7d5fc78bf1fa97895912dc6554d699209f7.zip chromium_src-f62ac7d5fc78bf1fa97895912dc6554d699209f7.tar.gz chromium_src-f62ac7d5fc78bf1fa97895912dc6554d699209f7.tar.bz2 |
Base: Move platform_file.* to files/file.*
PlatformFile has grown beyond the initial expectations and it doesn't make
sense to continue supporting individual function wrappers instead of a
proper file class.
BUG=322664
TEST=base_unittests
R=brettw@chromium.org
Review URL: https://codereview.chromium.org/93513002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238504 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/files')
-rw-r--r-- | base/files/file.cc | 53 | ||||
-rw-r--r-- | base/files/file.h | 496 | ||||
-rw-r--r-- | base/files/file_posix.cc | 251 | ||||
-rw-r--r-- | base/files/file_unittest.cc | 344 | ||||
-rw-r--r-- | base/files/file_win.cc | 228 |
5 files changed, 663 insertions, 709 deletions
diff --git a/base/files/file.cc b/base/files/file.cc index bb411b8..4902f15 100644 --- a/base/files/file.cc +++ b/base/files/file.cc @@ -2,30 +2,63 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/files/file.h" + +// TODO(rvargas): remove this (needed for kInvalidPlatformFileValue). #include "base/platform_file.h" namespace base { -PlatformFileInfo::PlatformFileInfo() +File::Info::Info() : size(0), is_directory(false), is_symbolic_link(false) { } -PlatformFileInfo::~PlatformFileInfo() {} +File::Info::~Info() { +} + +File::File() + : file_(kInvalidPlatformFileValue), + error_(FILE_OK), + created_(false), + async_(false) { +} #if !defined(OS_NACL) -PlatformFile CreatePlatformFile(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error) { +File::File(const FilePath& name, uint32 flags) + : file_(kInvalidPlatformFileValue), + error_(FILE_OK), + created_(false), + async_(false) { if (name.ReferencesParent()) { - if (error) - *error = PLATFORM_FILE_ERROR_ACCESS_DENIED; - return kInvalidPlatformFileValue; + error_ = FILE_ERROR_ACCESS_DENIED; + return; } - return CreatePlatformFileUnsafe(name, flags, created, error); + CreateBaseFileUnsafe(name, flags); } #endif +File::File(RValue other) + : file_(other.object->TakePlatformFile()), + error_(other.object->error()), + created_(other.object->created()), + async_(other.object->async_) { +} + +File::~File() { + Close(); +} + +File& File::operator=(RValue other) { + if (this != other.object) { + Close(); + SetPlatformFile(other.object->TakePlatformFile()); + error_ = other.object->error(); + created_ = other.object->created(); + async_ = other.object->async_; + } + return *this; +} + } // namespace base diff --git a/base/files/file.h b/base/files/file.h index 62b5c35..d1e0e8c 100644 --- a/base/files/file.h +++ b/base/files/file.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_PLATFORM_FILE_H_ -#define BASE_PLATFORM_FILE_H_ +#ifndef BASE_FILES_FILE_H_ +#define BASE_FILES_FILE_H_ #include "build/build_config.h" #if defined(OS_WIN) @@ -15,270 +15,266 @@ #include "base/base_export.h" #include "base/basictypes.h" #include "base/files/file_path.h" +#include "base/move.h" #include "base/time/time.h" -namespace base { - -// PLATFORM_FILE_(OPEN|CREATE).* are mutually exclusive. You should specify -// exactly one of the five (possibly combining with other flags) when opening -// or creating a file. -// PLATFORM_FILE_(WRITE|APPEND) are mutually exclusive. This is so that APPEND -// behavior will be consistent with O_APPEND on POSIX. -// PLATFORM_FILE_EXCLUSIVE_(READ|WRITE) only grant exclusive access to the file -// on creation on POSIX; for existing files, consider using LockPlatformFile(). -enum PlatformFileFlags { - PLATFORM_FILE_OPEN = 1 << 0, // Opens a file, only if it exists. - PLATFORM_FILE_CREATE = 1 << 1, // Creates a new file, only if it - // does not already exist. - PLATFORM_FILE_OPEN_ALWAYS = 1 << 2, // May create a new file. - PLATFORM_FILE_CREATE_ALWAYS = 1 << 3, // May overwrite an old file. - PLATFORM_FILE_OPEN_TRUNCATED = 1 << 4, // Opens a file and truncates it, - // only if it exists. - PLATFORM_FILE_READ = 1 << 5, - PLATFORM_FILE_WRITE = 1 << 6, - PLATFORM_FILE_APPEND = 1 << 7, - PLATFORM_FILE_EXCLUSIVE_READ = 1 << 8, // EXCLUSIVE is opposite of Windows - // SHARE - PLATFORM_FILE_EXCLUSIVE_WRITE = 1 << 9, - PLATFORM_FILE_ASYNC = 1 << 10, - PLATFORM_FILE_TEMPORARY = 1 << 11, // Used on Windows only - PLATFORM_FILE_HIDDEN = 1 << 12, // Used on Windows only - PLATFORM_FILE_DELETE_ON_CLOSE = 1 << 13, - - PLATFORM_FILE_WRITE_ATTRIBUTES = 1 << 14, // Used on Windows only - - PLATFORM_FILE_SHARE_DELETE = 1 << 15, // Used on Windows only - - PLATFORM_FILE_TERMINAL_DEVICE = 1 << 16, // Serial port flags - PLATFORM_FILE_BACKUP_SEMANTICS = 1 << 17, // Used on Windows only - - PLATFORM_FILE_EXECUTE = 1 << 18, // Used on Windows only -}; - -// This enum has been recorded in multiple histograms. If the order of the -// fields needs to change, please ensure that those histograms are obsolete or -// have been moved to a different enum. -// -// PLATFORM_FILE_ERROR_ACCESS_DENIED is returned when a call fails because of -// a filesystem restriction. PLATFORM_FILE_ERROR_SECURITY is returned when a -// browser policy doesn't allow the operation to be executed. -enum PlatformFileError { - PLATFORM_FILE_OK = 0, - PLATFORM_FILE_ERROR_FAILED = -1, - PLATFORM_FILE_ERROR_IN_USE = -2, - PLATFORM_FILE_ERROR_EXISTS = -3, - PLATFORM_FILE_ERROR_NOT_FOUND = -4, - PLATFORM_FILE_ERROR_ACCESS_DENIED = -5, - PLATFORM_FILE_ERROR_TOO_MANY_OPENED = -6, - PLATFORM_FILE_ERROR_NO_MEMORY = -7, - PLATFORM_FILE_ERROR_NO_SPACE = -8, - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY = -9, - PLATFORM_FILE_ERROR_INVALID_OPERATION = -10, - PLATFORM_FILE_ERROR_SECURITY = -11, - PLATFORM_FILE_ERROR_ABORT = -12, - PLATFORM_FILE_ERROR_NOT_A_FILE = -13, - PLATFORM_FILE_ERROR_NOT_EMPTY = -14, - PLATFORM_FILE_ERROR_INVALID_URL = -15, - PLATFORM_FILE_ERROR_IO = -16, - // Put new entries here and increment PLATFORM_FILE_ERROR_MAX. - PLATFORM_FILE_ERROR_MAX = -17 -}; +#if defined(OS_WIN) +#include "base/win/scoped_handle.h" +#endif -// This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. -enum PlatformFileWhence { - PLATFORM_FILE_FROM_BEGIN = 0, - PLATFORM_FILE_FROM_CURRENT = 1, - PLATFORM_FILE_FROM_END = 2 -}; +namespace base { -// Used to hold information about a given file. -// If you add more fields to this structure (platform-specific fields are OK), -// make sure to update all functions that use it in file_util_{win|posix}.cc -// too, and the ParamTraits<base::PlatformFileInfo> implementation in -// chrome/common/common_param_traits.cc. -struct BASE_EXPORT PlatformFileInfo { - PlatformFileInfo(); - ~PlatformFileInfo(); +#if defined(OS_WIN) +typedef HANDLE PlatformFile; +#elif defined(OS_POSIX) +typedef int PlatformFile; +#endif - // The size of the file in bytes. Undefined when is_directory is true. - int64 size; - // True if the file corresponds to a directory. - bool is_directory; +// Thin wrapper around an OS-level file. +// Note that this class does not provide any support for asynchronous IO, other +// than the ability to create asynchronous handles on Windows. +// +// Note about const: this class does not attempt to determine if the underlying +// file system object is affected by a particular method in order to consider +// that method const or not. Only methods that deal with member variables in an +// obvious non-modifying way are marked as const. Any method that forward calls +// to the OS is not considered const, even if there is no apparent change to +// member variables. +class BASE_EXPORT File { + MOVE_ONLY_TYPE_FOR_CPP_03(File, RValue) - // True if the file corresponds to a symbolic link. - bool is_symbolic_link; + public: + // FLAG_(OPEN|CREATE).* are mutually exclusive. You should specify exactly one + // of the five (possibly combining with other flags) when opening or creating + // a file. + // FLAG_(WRITE|APPEND) are mutually exclusive. This is so that APPEND behavior + // will be consistent with O_APPEND on POSIX. + // FLAG_EXCLUSIVE_(READ|WRITE) only grant exclusive access to the file on + // creation on POSIX; for existing files, consider using Lock(). + enum Flags { + FLAG_OPEN = 1 << 0, // Opens a file, only if it exists. + FLAG_CREATE = 1 << 1, // Creates a new file, only if it does not + // already exist. + FLAG_OPEN_ALWAYS = 1 << 2, // May create a new file. + FLAG_CREATE_ALWAYS = 1 << 3, // May overwrite an old file. + FLAG_OPEN_TRUNCATED = 1 << 4, // Opens a file and truncates it, only if it + // exists. + FLAG_READ = 1 << 5, + FLAG_WRITE = 1 << 6, + FLAG_APPEND = 1 << 7, + FLAG_EXCLUSIVE_READ = 1 << 8, // EXCLUSIVE is opposite of Windows SHARE. + FLAG_EXCLUSIVE_WRITE = 1 << 9, + FLAG_ASYNC = 1 << 10, + FLAG_TEMPORARY = 1 << 11, // Used on Windows only. + FLAG_HIDDEN = 1 << 12, // Used on Windows only. + FLAG_DELETE_ON_CLOSE = 1 << 13, + FLAG_WRITE_ATTRIBUTES = 1 << 14, // Used on Windows only. + FLAG_SHARE_DELETE = 1 << 15, // Used on Windows only. + FLAG_TERMINAL_DEVICE = 1 << 16, // Serial port flags. + FLAG_BACKUP_SEMANTICS = 1 << 17, // Used on Windows only. + FLAG_EXECUTE = 1 << 18, // Used on Windows only. + }; + + // This enum has been recorded in multiple histograms. If the order of the + // fields needs to change, please ensure that those histograms are obsolete or + // have been moved to a different enum. + // + // FILE_ERROR_ACCESS_DENIED is returned when a call fails because of a + // filesystem restriction. FILE_ERROR_SECURITY is returned when a browser + // policy doesn't allow the operation to be executed. + enum Error { + FILE_OK = 0, + FILE_ERROR_FAILED = -1, + FILE_ERROR_IN_USE = -2, + FILE_ERROR_EXISTS = -3, + FILE_ERROR_NOT_FOUND = -4, + FILE_ERROR_ACCESS_DENIED = -5, + FILE_ERROR_TOO_MANY_OPENED = -6, + FILE_ERROR_NO_MEMORY = -7, + FILE_ERROR_NO_SPACE = -8, + FILE_ERROR_NOT_A_DIRECTORY = -9, + FILE_ERROR_INVALID_OPERATION = -10, + FILE_ERROR_SECURITY = -11, + FILE_ERROR_ABORT = -12, + FILE_ERROR_NOT_A_FILE = -13, + FILE_ERROR_NOT_EMPTY = -14, + FILE_ERROR_INVALID_URL = -15, + FILE_ERROR_IO = -16, + // Put new entries here and increment FILE_ERROR_MAX. + FILE_ERROR_MAX = -17 + }; + + // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. + enum Whence { + FROM_BEGIN = 0, + FROM_CURRENT = 1, + FROM_END = 2 + }; + + // Used to hold information about a given file. + // If you add more fields to this structure (platform-specific fields are OK), + // make sure to update all functions that use it in file_util_{win|posix}.cc + // too, and the ParamTraits<base::PlatformFileInfo> implementation in + // chrome/common/common_param_traits.cc. + struct BASE_EXPORT Info { + Info(); + ~Info(); + + // The size of the file in bytes. Undefined when is_directory is true. + int64 size; + + // True if the file corresponds to a directory. + bool is_directory; + + // True if the file corresponds to a symbolic link. + bool is_symbolic_link; + + // The last modified time of a file. + base::Time last_modified; + + // The last accessed time of a file. + base::Time last_accessed; + + // The creation time of a file. + base::Time creation_time; + }; + + File(); + + // Creates or opens the given file. This will fail with 'access denied' if the + // |name| contains path traversal ('..') components. + File(const FilePath& name, uint32 flags); + + // Takes ownership of |platform_file|. + explicit File(PlatformFile platform_file); + + // Move constructor for C++03 move emulation of this type. + File(RValue other); + + ~File(); + + // Move operator= for C++03 move emulation of this type. + File& operator=(RValue other); + + // Creates or opens the given file, allowing paths with traversal ('..') + // components. Use only with extreme care. + void CreateBaseFileUnsafe(const FilePath& name, uint32 flags); + + bool IsValid() const; + + // Returns true if a new file was created (or an old one truncated to zero + // length to simulate a new file, which can happen with + // FLAG_CREATE_ALWAYS), and false otherwise. + bool created() const { return created_; } + + // Returns the OS result of opening this file. + Error error() const { return error_; } + + PlatformFile GetPlatformFile() const { return file_; } + PlatformFile TakePlatformFile(); + + // Destroying this object closes the file automatically. + void Close(); + + // Changes current position in the file to an |offset| relative to an origin + // defined by |whence|. Returns the resultant current position in the file + // (relative to the start) or -1 in case of error. + int64 Seek(Whence whence, int64 offset); + + // Reads the given number of bytes (or until EOF is reached) starting with the + // given offset. Returns the number of bytes read, or -1 on error. Note that + // this function makes a best effort to read all data on all platforms, so it + // is not intended for stream oriented files but instead for cases when the + // normal expectation is that actually |size| bytes are read unless there is + // an error. + int Read(int64 offset, char* data, int size); + + // Same as above but without seek. + int ReadAtCurrentPos(char* data, int size); + + // Reads the given number of bytes (or until EOF is reached) starting with the + // given offset, but does not make any effort to read all data on all + // platforms. Returns the number of bytes read, or -1 on error. + int ReadNoBestEffort(int64 offset, char* data, int size); + + // Same as above but without seek. + int ReadAtCurrentPosNoBestEffort(char* data, int size); + + // Writes the given buffer into the file at the given offset, overwritting any + // data that was previously there. Returns the number of bytes written, or -1 + // on error. Note that this function makes a best effort to write all data on + // all platforms. + // Ignores the offset and writes to the end of the file if the file was opened + // with FLAG_APPEND. + int Write(int64 offset, const char* data, int size); + + // Save as above but without seek. + int WriteAtCurrentPos(const char* data, int size); + + // Save as above but does not make any effort to write all data on all + // platforms. Returns the number of bytes written, or -1 on error. + int WriteAtCurrentPosNoBestEffort(const char* data, int size); + + // Truncates the file to the given length. If |length| is greater than the + // current size of the file, the file is extended with zeros. If the file + // doesn't exist, |false| is returned. + bool Truncate(int64 length); - // The last modified time of a file. - base::Time last_modified; + // Flushes the buffers. + bool Flush(); + + // Updates the file times. + bool SetTimes(Time last_access_time, Time last_modified_time); + + // Returns some basic information for the given file. + bool GetInfo(Info* info); + + // Attempts to take an exclusive write lock on the file. Returns immediately + // (i.e. does not wait for another process to unlock the file). If the lock + // was obtained, the result will be FILE_OK. A lock only guarantees + // that other processes may not also take a lock on the same file with the + // same API - it may still be opened, renamed, unlinked, etc. + // + // Common semantics: + // * Locks are held by processes, but not inherited by child processes. + // * Locks are released by the OS on file close or process termination. + // * Locks are reliable only on local filesystems. + // * Duplicated file handles may also write to locked files. + // Windows-specific semantics: + // * Locks are mandatory for read/write APIs, advisory for mapping APIs. + // * Within a process, locking the same file (by the same or new handle) + // will fail. + // POSIX-specific semantics: + // * Locks are advisory only. + // * Within a process, locking the same file (by the same or new handle) + // will succeed. + // * Closing any descriptor on a given file releases the lock. + Error Lock(); + + // Unlock a file previously locked. + Error Unlock(); - // The last accessed time of a file. - base::Time last_accessed; +#if defined(OS_WIN) + static Error OSErrorToFileError(DWORD last_error); +#elif defined(OS_POSIX) + static Error OSErrorToFileError(int saved_errno); +#endif - // The creation time of a file. - base::Time creation_time; -}; + private: + void SetPlatformFile(PlatformFile file); #if defined(OS_WIN) -typedef HANDLE PlatformFile; -const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE; -BASE_EXPORT PlatformFileError LastErrorToPlatformFileError(DWORD last_error); + win::ScopedHandle file_; #elif defined(OS_POSIX) -typedef int PlatformFile; -const PlatformFile kInvalidPlatformFileValue = -1; -BASE_EXPORT PlatformFileError ErrnoToPlatformFileError(int saved_errno); + PlatformFile file_; #endif -// Creates or opens the given file. If |created| is provided, it will be set to -// true if a new file was created [or an old one truncated to zero length to -// simulate a new file, which can happen with PLATFORM_FILE_CREATE_ALWAYS], and -// false otherwise. |error| can be NULL. -// -// This function fails with 'access denied' if the |name| contains path -// traversal ('..') components. -BASE_EXPORT PlatformFile CreatePlatformFile(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error); - -// Same as CreatePlatformFile but allows paths with traversal (like \..\) -// components. Use only with extreme care. -BASE_EXPORT PlatformFile CreatePlatformFileUnsafe(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error); - -BASE_EXPORT FILE* FdopenPlatformFile(PlatformFile file, const char* mode); - -// Closes a file handle. Returns |true| on success and |false| otherwise. -BASE_EXPORT bool ClosePlatformFile(PlatformFile file); - -// Changes current position in the file to an |offset| relative to an origin -// defined by |whence|. Returns the resultant current position in the file -// (relative to the start) or -1 in case of error. -BASE_EXPORT int64 SeekPlatformFile(PlatformFile file, - PlatformFileWhence whence, - int64 offset); - -// Reads the given number of bytes (or until EOF is reached) starting with the -// given offset. Returns the number of bytes read, or -1 on error. Note that -// this function makes a best effort to read all data on all platforms, so it is -// not intended for stream oriented files but instead for cases when the normal -// expectation is that actually |size| bytes are read unless there is an error. -BASE_EXPORT int ReadPlatformFile(PlatformFile file, int64 offset, - char* data, int size); - -// Same as above but without seek. -BASE_EXPORT int ReadPlatformFileAtCurrentPos(PlatformFile file, - char* data, int size); - -// Reads the given number of bytes (or until EOF is reached) starting with the -// given offset, but does not make any effort to read all data on all platforms. -// Returns the number of bytes read, or -1 on error. -BASE_EXPORT int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, - char* data, int size); - -// Same as above but without seek. -BASE_EXPORT int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, - char* data, int size); - -// Writes the given buffer into the file at the given offset, overwritting any -// data that was previously there. Returns the number of bytes written, or -1 -// on error. Note that this function makes a best effort to write all data on -// all platforms. -// Ignores the offset and writes to the end of the file if the file was opened -// with PLATFORM_FILE_APPEND. -BASE_EXPORT int WritePlatformFile(PlatformFile file, int64 offset, - const char* data, int size); - -// Save as above but without seek. -BASE_EXPORT int WritePlatformFileAtCurrentPos(PlatformFile file, - const char* data, int size); - -// Save as above but does not make any effort to write all data on all -// platforms. Returns the number of bytes written, or -1 on error. -BASE_EXPORT int WritePlatformFileCurPosNoBestEffort(PlatformFile file, - const char* data, int size); - -// Truncates the given file to the given length. If |length| is greater than -// the current size of the file, the file is extended with zeros. If the file -// doesn't exist, |false| is returned. -BASE_EXPORT bool TruncatePlatformFile(PlatformFile file, int64 length); - -// Flushes the buffers of the given file. -BASE_EXPORT bool FlushPlatformFile(PlatformFile file); - -// Touches the given file. -BASE_EXPORT bool TouchPlatformFile(PlatformFile file, - const Time& last_access_time, - const Time& last_modified_time); - -// Returns some information for the given file. -BASE_EXPORT bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); - -// Attempts to take an exclusive write lock on the file. Returns immediately -// (i.e. does not wait for another process to unlock the file). If the lock -// was obtained, the result will be PLATFORM_FILE_OK. A lock only guarantees -// that other processes may not also take a lock on the same file with the -// same API - it may still be opened, renamed, unlinked, etc. -// -// Common semantics: -// * Locks are held by processes, but not inherited by child processes. -// * Locks are released by the OS on file handle close or process termination. -// * Locks are reliable only on local filesystems. -// * Duplicated file handles may also write to locked files. -// Windows-specific semantics: -// * Locks are mandatory for read/write APIs, advisory for mapping APIs. -// * Within a process, locking the same file (by the same or new handle) -// will fail. -// POSIX-specific semantics: -// * Locks are advisory only. -// * Within a process, locking the same file (by the same or new handle) -// will succeed. -// * Closing any descriptor on a given file releases the lock. -BASE_EXPORT PlatformFileError LockPlatformFile(PlatformFile file); - -// Unlock a file previously locked with LockPlatformFile. -BASE_EXPORT PlatformFileError UnlockPlatformFile(PlatformFile file); - -// Use this class to pass ownership of a PlatformFile to a receiver that may or -// may not want to accept it. This class does not own the storage for the -// PlatformFile. -// -// EXAMPLE: -// -// void MaybeProcessFile(PassPlatformFile pass_file) { -// if (...) { -// PlatformFile file = pass_file.ReleaseValue(); -// // Now, we are responsible for closing |file|. -// } -// } -// -// void OpenAndMaybeProcessFile(const FilePath& path) { -// PlatformFile file = CreatePlatformFile(path, ...); -// MaybeProcessFile(PassPlatformFile(&file)); -// if (file != kInvalidPlatformFileValue) -// ClosePlatformFile(file); -// } -// -class BASE_EXPORT PassPlatformFile { - public: - explicit PassPlatformFile(PlatformFile* value) : value_(value) { - } - - // Called to retrieve the PlatformFile stored in this object. The caller - // gains ownership of the PlatformFile and is now responsible for closing it. - // Any subsequent calls to this method will return an invalid PlatformFile. - PlatformFile ReleaseValue() { - PlatformFile temp = *value_; - *value_ = kInvalidPlatformFileValue; - return temp; - } - - private: - PlatformFile* value_; + Error error_; + bool created_; + bool async_; }; } // namespace base -#endif // BASE_PLATFORM_FILE_H_ +#endif // BASE_FILES_FILE_H_ diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc index 028a382..9d97c33 100644 --- a/base/files/file_posix.cc +++ b/base/files/file_posix.cc @@ -2,16 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/platform_file.h" +#include "base/files/file.h" -#include <fcntl.h> #include <errno.h> +#include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include "base/files/file_path.h" #include "base/logging.h" #include "base/metrics/sparse_histogram.h" +// TODO(rvargas): remove this (needed for kInvalidPlatformFileValue). +#include "base/platform_file.h" #include "base/posix/eintr_wrapper.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" @@ -23,9 +25,9 @@ namespace base { // Make sure our Whence mappings match the system headers. -COMPILE_ASSERT(PLATFORM_FILE_FROM_BEGIN == SEEK_SET && - PLATFORM_FILE_FROM_CURRENT == SEEK_CUR && - PLATFORM_FILE_FROM_END == SEEK_END, whence_matches_system); +COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET && + File::FROM_CURRENT == SEEK_CUR && + File::FROM_END == SEEK_END, whence_matches_system); namespace { @@ -75,15 +77,15 @@ static int CallFutimes(PlatformFile file, const struct timeval times[2]) { #endif } -static PlatformFileError CallFctnlFlock(PlatformFile file, bool do_lock) { +static File::Error CallFctnlFlock(PlatformFile file, bool do_lock) { struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; // Lock entire file. if (HANDLE_EINTR(fcntl(file, do_lock ? F_SETLK : F_UNLCK, &lock)) == -1) - return ErrnoToPlatformFileError(errno); - return PLATFORM_FILE_OK; + return File::OSErrorToFileError(errno); + return File::FILE_OK; } #else // defined(OS_NACL) @@ -109,9 +111,9 @@ static int CallFutimes(PlatformFile file, const struct timeval times[2]) { return 0; } -static PlatformFileError CallFctnlFlock(PlatformFile file, bool do_lock) { +static File::Error CallFctnlFlock(PlatformFile file, bool do_lock) { NOTIMPLEMENTED(); // NaCl doesn't implement flock struct. - return PLATFORM_FILE_ERROR_INVALID_OPERATION; + return File::FILE_ERROR_INVALID_OPERATION; } #endif // defined(OS_NACL) @@ -119,57 +121,53 @@ static PlatformFileError CallFctnlFlock(PlatformFile file, bool do_lock) { // NaCl doesn't implement system calls to open files directly. #if !defined(OS_NACL) -// TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here? -PlatformFile CreatePlatformFileUnsafe(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error) { +// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? +void File::CreateBaseFileUnsafe(const FilePath& name, uint32 flags) { base::ThreadRestrictions::AssertIOAllowed(); + DCHECK(!IsValid()); + DCHECK(!(flags & FLAG_ASYNC)); int open_flags = 0; - if (flags & PLATFORM_FILE_CREATE) + if (flags & FLAG_CREATE) open_flags = O_CREAT | O_EXCL; - if (created) - *created = false; + created_ = false; - if (flags & PLATFORM_FILE_CREATE_ALWAYS) { + if (flags & FLAG_CREATE_ALWAYS) { DCHECK(!open_flags); open_flags = O_CREAT | O_TRUNC; } - if (flags & PLATFORM_FILE_OPEN_TRUNCATED) { + if (flags & FLAG_OPEN_TRUNCATED) { DCHECK(!open_flags); - DCHECK(flags & PLATFORM_FILE_WRITE); + DCHECK(flags & FLAG_WRITE); open_flags = O_TRUNC; } - if (!open_flags && !(flags & PLATFORM_FILE_OPEN) && - !(flags & PLATFORM_FILE_OPEN_ALWAYS)) { + if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) { NOTREACHED(); errno = EOPNOTSUPP; - if (error) - *error = PLATFORM_FILE_ERROR_FAILED; - return kInvalidPlatformFileValue; + error_ = FILE_ERROR_FAILED; + return; } - if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) { + if (flags & FLAG_WRITE && flags & FLAG_READ) { open_flags |= O_RDWR; - } else if (flags & PLATFORM_FILE_WRITE) { + } else if (flags & FLAG_WRITE) { open_flags |= O_WRONLY; - } else if (!(flags & PLATFORM_FILE_READ) && - !(flags & PLATFORM_FILE_WRITE_ATTRIBUTES) && - !(flags & PLATFORM_FILE_APPEND) && - !(flags & PLATFORM_FILE_OPEN_ALWAYS)) { + } else if (!(flags & FLAG_READ) && + !(flags & FLAG_WRITE_ATTRIBUTES) && + !(flags & FLAG_APPEND) && + !(flags & FLAG_OPEN_ALWAYS)) { NOTREACHED(); } - if (flags & PLATFORM_FILE_TERMINAL_DEVICE) + if (flags & FLAG_TERMINAL_DEVICE) open_flags |= O_NOCTTY | O_NDELAY; - if (flags & PLATFORM_FILE_APPEND && flags & PLATFORM_FILE_READ) + if (flags & FLAG_APPEND && flags & FLAG_READ) open_flags |= O_APPEND | O_RDWR; - else if (flags & PLATFORM_FILE_APPEND) + else if (flags & FLAG_APPEND) open_flags |= O_APPEND | O_WRONLY; COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); @@ -179,70 +177,73 @@ PlatformFile CreatePlatformFileUnsafe(const FilePath& name, mode |= S_IRGRP | S_IROTH; #endif - int descriptor = - HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); + int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); - if (flags & PLATFORM_FILE_OPEN_ALWAYS) { + if (flags & FLAG_OPEN_ALWAYS) { if (descriptor < 0) { open_flags |= O_CREAT; - if (flags & PLATFORM_FILE_EXCLUSIVE_READ || - flags & PLATFORM_FILE_EXCLUSIVE_WRITE) { + if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE) open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW - } - descriptor = HANDLE_EINTR( - open(name.value().c_str(), open_flags, mode)); - if (created && descriptor >= 0) - *created = true; + + descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); + if (descriptor >= 0) + created_ = true; } } - if (created && (descriptor >= 0) && - (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE))) - *created = true; + if (descriptor >= 0 && (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))) + created_ = true; - if ((descriptor >= 0) && (flags & PLATFORM_FILE_DELETE_ON_CLOSE)) { + if ((descriptor >= 0) && (flags & FLAG_DELETE_ON_CLOSE)) unlink(name.value().c_str()); - } - if (error) { - if (descriptor >= 0) - *error = PLATFORM_FILE_OK; - else - *error = ErrnoToPlatformFileError(errno); - } + if (descriptor >= 0) + error_ = FILE_OK; + else + error_ = File::OSErrorToFileError(errno); - return descriptor; + file_ = descriptor; } +#endif // !defined(OS_NACL) -FILE* FdopenPlatformFile(PlatformFile file, const char* mode) { - return fdopen(file, mode); +bool File::IsValid() const { + return file_ >= 0; } -#endif // !defined(OS_NACL) -bool ClosePlatformFile(PlatformFile file) { +PlatformFile File::TakePlatformFile() { + PlatformFile file = file_; + file_ = kInvalidPlatformFileValue; + return file; +} + +void File::Close() { base::ThreadRestrictions::AssertIOAllowed(); - return !IGNORE_EINTR(close(file)); + if (!IsValid()) + return; + + if (!IGNORE_EINTR(close(file_))) + file_ = kInvalidPlatformFileValue; } -int64 SeekPlatformFile(PlatformFile file, - PlatformFileWhence whence, - int64 offset) { +int64 File::Seek(Whence whence, int64 offset) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0 || offset < 0) + DCHECK(IsValid()); + if (file_ < 0 || offset < 0) return -1; - return lseek(file, static_cast<off_t>(offset), static_cast<int>(whence)); + return lseek(file_, static_cast<off_t>(offset), static_cast<int>(whence)); } -int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { +int File::Read(int64 offset, char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0 || size < 0) + DCHECK(IsValid()); + if (size < 0) return -1; int bytes_read = 0; int rv; do { - rv = HANDLE_EINTR(pread(file, data + bytes_read, + rv = HANDLE_EINTR(pread(file_, data + bytes_read, size - bytes_read, offset + bytes_read)); if (rv <= 0) break; @@ -253,15 +254,16 @@ int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { return bytes_read ? bytes_read : rv; } -int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) { +int File::ReadAtCurrentPos(char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0 || size < 0) + DCHECK(IsValid()); + if (size < 0) return -1; int bytes_read = 0; int rv; do { - rv = HANDLE_EINTR(read(file, data, size)); + rv = HANDLE_EINTR(read(file_, data, size)); if (rv <= 0) break; @@ -271,38 +273,36 @@ int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) { return bytes_read ? bytes_read : rv; } -int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, - char* data, int size) { +int File::ReadNoBestEffort(int64 offset, char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0) - return -1; + DCHECK(IsValid()); - return HANDLE_EINTR(pread(file, data, size, offset)); + return HANDLE_EINTR(pread(file_, data, size, offset)); } -int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, - char* data, int size) { +int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0 || size < 0) + DCHECK(IsValid()); + if (size < 0) return -1; - return HANDLE_EINTR(read(file, data, size)); + return HANDLE_EINTR(read(file_, data, size)); } -int WritePlatformFile(PlatformFile file, int64 offset, - const char* data, int size) { +int File::Write(int64 offset, const char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (IsOpenAppend(file)) - return WritePlatformFileAtCurrentPos(file, data, size); + if (IsOpenAppend(file_)) + return WriteAtCurrentPos(data, size); - if (file < 0 || size < 0) + DCHECK(IsValid()); + if (size < 0) return -1; int bytes_written = 0; int rv; do { - rv = HANDLE_EINTR(pwrite(file, data + bytes_written, + rv = HANDLE_EINTR(pwrite(file_, data + bytes_written, size - bytes_written, offset + bytes_written)); if (rv <= 0) break; @@ -313,16 +313,16 @@ int WritePlatformFile(PlatformFile file, int64 offset, return bytes_written ? bytes_written : rv; } -int WritePlatformFileAtCurrentPos(PlatformFile file, - const char* data, int size) { +int File::WriteAtCurrentPos(const char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0 || size < 0) + DCHECK(IsValid()); + if (size < 0) return -1; int bytes_written = 0; int rv; do { - rv = HANDLE_EINTR(write(file, data, size)); + rv = HANDLE_EINTR(write(file_, data, size)); if (rv <= 0) break; @@ -332,44 +332,43 @@ int WritePlatformFileAtCurrentPos(PlatformFile file, return bytes_written ? bytes_written : rv; } -int WritePlatformFileCurPosNoBestEffort(PlatformFile file, - const char* data, int size) { +int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0 || size < 0) + DCHECK(IsValid()); + if (size < 0) return -1; - return HANDLE_EINTR(write(file, data, size)); + return HANDLE_EINTR(write(file_, data, size)); } -bool TruncatePlatformFile(PlatformFile file, int64 length) { +bool File::Truncate(int64 length) { base::ThreadRestrictions::AssertIOAllowed(); - return ((file >= 0) && !CallFtruncate(file, length)); + DCHECK(IsValid()); + return !CallFtruncate(file_, length); } -bool FlushPlatformFile(PlatformFile file) { +bool File::Flush() { base::ThreadRestrictions::AssertIOAllowed(); - return !CallFsync(file); + DCHECK(IsValid()); + return !CallFsync(file_); } -bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time, - const base::Time& last_modified_time) { +bool File::SetTimes(Time last_access_time, Time last_modified_time) { base::ThreadRestrictions::AssertIOAllowed(); - if (file < 0) - return false; + DCHECK(IsValid()); timeval times[2]; times[0] = last_access_time.ToTimeVal(); times[1] = last_modified_time.ToTimeVal(); - return !CallFutimes(file, times); + return !CallFutimes(file_, times); } -bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { - if (!info) - return false; +bool File::GetInfo(Info* info) { + DCHECK(IsValid()); stat_wrapper_t file_info; - if (CallFstat(file, &file_info)) + if (CallFstat(file_, &file_info)) return false; info->is_directory = S_ISDIR(file_info.st_mode); @@ -422,44 +421,50 @@ bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { return true; } -PlatformFileError LockPlatformFile(PlatformFile file) { - return CallFctnlFlock(file, true); +File::Error File::Lock() { + return CallFctnlFlock(file_, true); } -PlatformFileError UnlockPlatformFile(PlatformFile file) { - return CallFctnlFlock(file, false); +File::Error File::Unlock() { + return CallFctnlFlock(file_, false); } -PlatformFileError ErrnoToPlatformFileError(int saved_errno) { +// Static. +File::Error File::OSErrorToFileError(int saved_errno) { switch (saved_errno) { case EACCES: case EISDIR: case EROFS: case EPERM: - return PLATFORM_FILE_ERROR_ACCESS_DENIED; + return FILE_ERROR_ACCESS_DENIED; #if !defined(OS_NACL) // ETXTBSY not defined by NaCl. case ETXTBSY: - return PLATFORM_FILE_ERROR_IN_USE; + return FILE_ERROR_IN_USE; #endif case EEXIST: - return PLATFORM_FILE_ERROR_EXISTS; + return FILE_ERROR_EXISTS; case ENOENT: - return PLATFORM_FILE_ERROR_NOT_FOUND; + return FILE_ERROR_NOT_FOUND; case EMFILE: - return PLATFORM_FILE_ERROR_TOO_MANY_OPENED; + return FILE_ERROR_TOO_MANY_OPENED; case ENOMEM: - return PLATFORM_FILE_ERROR_NO_MEMORY; + return FILE_ERROR_NO_MEMORY; case ENOSPC: - return PLATFORM_FILE_ERROR_NO_SPACE; + return FILE_ERROR_NO_SPACE; case ENOTDIR: - return PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; + return FILE_ERROR_NOT_A_DIRECTORY; default: #if !defined(OS_NACL) // NaCl build has no metrics code. UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Posix", saved_errno); #endif - return PLATFORM_FILE_ERROR_FAILED; + return FILE_ERROR_FAILED; } } +void File::SetPlatformFile(PlatformFile file) { + DCHECK_EQ(file_, kInvalidPlatformFileValue); + file_ = file; +} + } // namespace base diff --git a/base/files/file_unittest.cc b/base/files/file_unittest.cc index 0da3cf0..178f867 100644 --- a/base/files/file_unittest.cc +++ b/base/files/file_unittest.cc @@ -3,193 +3,148 @@ // found in the LICENSE file. #include "base/file_util.h" +#include "base/files/file.h" #include "base/files/scoped_temp_dir.h" -#include "base/platform_file.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" +using base::File; using base::FilePath; -namespace { - -// Reads from a file the given number of bytes, or until EOF is reached. -// Returns the number of bytes read. -int ReadFully(base::PlatformFile file, int64 offset, char* data, int size) { - return base::ReadPlatformFile(file, offset, data, size); -} - -// Writes the given number of bytes to a file. -// Returns the number of bytes written. -int WriteFully(base::PlatformFile file, int64 offset, - const char* data, int size) { - return base::WritePlatformFile(file, offset, data, size); -} - -} // namespace - -TEST(PlatformFile, CreatePlatformFile) { +TEST(File, Create) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath file_path = temp_dir.path().AppendASCII("create_file_1"); - // Open a file that doesn't exist. - base::PlatformFileError error_code = base::PLATFORM_FILE_OK; - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, - NULL, - &error_code); - EXPECT_EQ(base::kInvalidPlatformFileValue, file); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, error_code); - - // Open or create a file. - bool created = false; - error_code = base::PLATFORM_FILE_OK; - file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ, - &created, - &error_code); - EXPECT_NE(base::kInvalidPlatformFileValue, file); - EXPECT_TRUE(created); - EXPECT_EQ(base::PLATFORM_FILE_OK, error_code); - base::ClosePlatformFile(file); - - // Open an existing file. - created = false; - file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, - &created, - &error_code); - EXPECT_NE(base::kInvalidPlatformFileValue, file); - EXPECT_FALSE(created); - EXPECT_EQ(base::PLATFORM_FILE_OK, error_code); - base::ClosePlatformFile(file); - - // Create a file that exists. - file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ, - &created, - &error_code); - EXPECT_EQ(base::kInvalidPlatformFileValue, file); - EXPECT_FALSE(created); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, error_code); - - // Create or overwrite a file. - error_code = base::PLATFORM_FILE_OK; - file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ, - &created, - &error_code); - EXPECT_NE(base::kInvalidPlatformFileValue, file); - EXPECT_TRUE(created); - EXPECT_EQ(base::PLATFORM_FILE_OK, error_code); - base::ClosePlatformFile(file); - - // Create a delete-on-close file. - created = false; - file_path = temp_dir.path().AppendASCII("create_file_2"); - file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_DELETE_ON_CLOSE | - base::PLATFORM_FILE_READ, - &created, - &error_code); - EXPECT_NE(base::kInvalidPlatformFileValue, file); - EXPECT_TRUE(created); - EXPECT_EQ(base::PLATFORM_FILE_OK, error_code); - - EXPECT_TRUE(base::ClosePlatformFile(file)); + { + // Open a file that doesn't exist. + File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + EXPECT_FALSE(file.IsValid()); + EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error()); + } + + { + // Open or create a file. + File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ); + EXPECT_TRUE(file.IsValid()); + EXPECT_TRUE(file.created()); + EXPECT_EQ(base::File::FILE_OK, file.error()); + } + + { + // Open an existing file. + File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + EXPECT_TRUE(file.IsValid()); + EXPECT_FALSE(file.created()); + EXPECT_EQ(base::File::FILE_OK, file.error()); + + // This time verify closing the file. + file.Close(); + EXPECT_FALSE(file.IsValid()); + } + + { + // Create a file that exists. + File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ); + EXPECT_FALSE(file.IsValid()); + EXPECT_FALSE(file.created()); + EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error()); + } + + { + // Create or overwrite a file. + File file(file_path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ); + EXPECT_TRUE(file.IsValid()); + EXPECT_TRUE(file.created()); + EXPECT_EQ(base::File::FILE_OK, file.error()); + } + + { + // Create a delete-on-close file. + file_path = temp_dir.path().AppendASCII("create_file_2"); + File file(file_path, + base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | + base::File::FLAG_DELETE_ON_CLOSE); + EXPECT_TRUE(file.IsValid()); + EXPECT_TRUE(file.created()); + EXPECT_EQ(base::File::FILE_OK, file.error()); + } + EXPECT_FALSE(base::PathExists(file_path)); } -TEST(PlatformFile, DeleteOpenFile) { +TEST(File, DeleteOpenFile) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath file_path = temp_dir.path().AppendASCII("create_file_1"); // Create a file. - bool created = false; - base::PlatformFileError error_code = base::PLATFORM_FILE_OK; - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_SHARE_DELETE, - &created, - &error_code); - EXPECT_NE(base::kInvalidPlatformFileValue, file); - EXPECT_TRUE(created); - EXPECT_EQ(base::PLATFORM_FILE_OK, error_code); + File file(file_path, + base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | + base::File::FLAG_SHARE_DELETE); + EXPECT_TRUE(file.IsValid()); + EXPECT_TRUE(file.created()); + EXPECT_EQ(base::File::FILE_OK, file.error()); // Open an existing file and mark it as delete on close. - created = false; - base::PlatformFile same_file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_DELETE_ON_CLOSE | - base::PLATFORM_FILE_READ, - &created, - &error_code); - EXPECT_NE(base::kInvalidPlatformFileValue, file); - EXPECT_FALSE(created); - EXPECT_EQ(base::PLATFORM_FILE_OK, error_code); + File same_file(file_path, + base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE | + base::File::FLAG_READ); + EXPECT_TRUE(file.IsValid()); + EXPECT_FALSE(same_file.created()); + EXPECT_EQ(base::File::FILE_OK, same_file.error()); // Close both handles and check that the file is gone. - base::ClosePlatformFile(file); - base::ClosePlatformFile(same_file); + file.Close(); + same_file.Close(); EXPECT_FALSE(base::PathExists(file_path)); } -TEST(PlatformFile, ReadWritePlatformFile) { +TEST(File, ReadWrite) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath file_path = temp_dir.path().AppendASCII("read_write_file"); - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_WRITE, - NULL, - NULL); - EXPECT_NE(base::kInvalidPlatformFileValue, file); + File file(file_path, + base::File::FLAG_CREATE | base::File::FLAG_READ | + base::File::FLAG_WRITE); + ASSERT_TRUE(file.IsValid()); char data_to_write[] = "test"; const int kTestDataSize = 4; // Write 0 bytes to the file. - int bytes_written = WriteFully(file, 0, data_to_write, 0); + int bytes_written = file.Write(0, data_to_write, 0); EXPECT_EQ(0, bytes_written); // Write "test" to the file. - bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize); + bytes_written = file.Write(0, data_to_write, kTestDataSize); EXPECT_EQ(kTestDataSize, bytes_written); // Read from EOF. char data_read_1[32]; - int bytes_read = ReadFully(file, kTestDataSize, data_read_1, kTestDataSize); + int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize); EXPECT_EQ(0, bytes_read); // Read from somewhere in the middle of the file. const int kPartialReadOffset = 1; - bytes_read = ReadFully(file, kPartialReadOffset, data_read_1, kTestDataSize); + bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize); EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read); for (int i = 0; i < bytes_read; i++) EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]); // Read 0 bytes. - bytes_read = ReadFully(file, 0, data_read_1, 0); + bytes_read = file.Read(0, data_read_1, 0); EXPECT_EQ(0, bytes_read); // Read the entire file. - bytes_read = ReadFully(file, 0, data_read_1, kTestDataSize); + bytes_read = file.Read(0, data_read_1, kTestDataSize); EXPECT_EQ(kTestDataSize, bytes_read); for (int i = 0; i < bytes_read; i++) EXPECT_EQ(data_to_write[i], data_read_1[i]); // Read again, but using the trivial native wrapper. - bytes_read = base::ReadPlatformFileNoBestEffort(file, 0, data_read_1, - kTestDataSize); + bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize); EXPECT_LE(bytes_read, kTestDataSize); for (int i = 0; i < bytes_read; i++) EXPECT_EQ(data_to_write[i], data_read_1[i]); @@ -197,7 +152,7 @@ TEST(PlatformFile, ReadWritePlatformFile) { // Write past the end of the file. const int kOffsetBeyondEndOfFile = 10; const int kPartialWriteLength = 2; - bytes_written = WriteFully(file, kOffsetBeyondEndOfFile, + bytes_written = file.Write(kOffsetBeyondEndOfFile, data_to_write, kPartialWriteLength); EXPECT_EQ(kPartialWriteLength, bytes_written); @@ -208,7 +163,7 @@ TEST(PlatformFile, ReadWritePlatformFile) { // Make sure the file was zero-padded. char data_read_2[32]; - bytes_read = ReadFully(file, 0, data_read_2, static_cast<int>(file_size)); + bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size)); EXPECT_EQ(file_size, bytes_read); for (int i = 0; i < kTestDataSize; i++) EXPECT_EQ(data_to_write[i], data_read_2[i]); @@ -216,92 +171,81 @@ TEST(PlatformFile, ReadWritePlatformFile) { EXPECT_EQ(0, data_read_2[i]); for (int i = kOffsetBeyondEndOfFile; i < file_size; i++) EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]); - - // Close the file handle to allow the temp directory to be deleted. - base::ClosePlatformFile(file); } -TEST(PlatformFile, AppendPlatformFile) { +TEST(File, Append) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath file_path = temp_dir.path().AppendASCII("append_file"); - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_APPEND, - NULL, - NULL); - EXPECT_NE(base::kInvalidPlatformFileValue, file); + File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND); + ASSERT_TRUE(file.IsValid()); char data_to_write[] = "test"; const int kTestDataSize = 4; // Write 0 bytes to the file. - int bytes_written = WriteFully(file, 0, data_to_write, 0); + int bytes_written = file.Write(0, data_to_write, 0); EXPECT_EQ(0, bytes_written); // Write "test" to the file. - bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize); + bytes_written = file.Write(0, data_to_write, kTestDataSize); EXPECT_EQ(kTestDataSize, bytes_written); - base::ClosePlatformFile(file); - file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_APPEND, - NULL, - NULL); - EXPECT_NE(base::kInvalidPlatformFileValue, file); + file.Close(); + File file2(file_path, + base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_APPEND); + ASSERT_TRUE(file2.IsValid()); + + // Test passing the file around. + file = file2.Pass(); + EXPECT_FALSE(file2.IsValid()); + ASSERT_TRUE(file.IsValid()); char append_data_to_write[] = "78"; const int kAppendDataSize = 2; // Append "78" to the file. - bytes_written = WriteFully(file, 0, append_data_to_write, kAppendDataSize); + bytes_written = file.Write(0, append_data_to_write, kAppendDataSize); EXPECT_EQ(kAppendDataSize, bytes_written); // Read the entire file. char data_read_1[32]; - int bytes_read = ReadFully(file, 0, data_read_1, + int bytes_read = file.Read(0, data_read_1, kTestDataSize + kAppendDataSize); EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read); for (int i = 0; i < kTestDataSize; i++) EXPECT_EQ(data_to_write[i], data_read_1[i]); for (int i = 0; i < kAppendDataSize; i++) EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]); - - // Close the file handle to allow the temp directory to be deleted. - base::ClosePlatformFile(file); } -TEST(PlatformFile, TruncatePlatformFile) { +TEST(File, Truncate) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath file_path = temp_dir.path().AppendASCII("truncate_file"); - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_WRITE, - NULL, - NULL); - EXPECT_NE(base::kInvalidPlatformFileValue, file); + File file(file_path, + base::File::FLAG_CREATE | base::File::FLAG_READ | + base::File::FLAG_WRITE); + ASSERT_TRUE(file.IsValid()); // Write "test" to the file. char data_to_write[] = "test"; int kTestDataSize = 4; - int bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize); + int bytes_written = file.Write(0, data_to_write, kTestDataSize); EXPECT_EQ(kTestDataSize, bytes_written); // Extend the file. const int kExtendedFileLength = 10; int64 file_size = 0; - EXPECT_TRUE(base::TruncatePlatformFile(file, kExtendedFileLength)); + EXPECT_TRUE(file.Truncate(kExtendedFileLength)); EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size)); EXPECT_EQ(kExtendedFileLength, file_size); // Make sure the file was zero-padded. char data_read[32]; - int bytes_read = ReadFully(file, 0, data_read, static_cast<int>(file_size)); + int bytes_read = file.Read(0, data_read, static_cast<int>(file_size)); EXPECT_EQ(file_size, bytes_read); for (int i = 0; i < kTestDataSize; i++) EXPECT_EQ(data_to_write[i], data_read[i]); @@ -310,39 +254,33 @@ TEST(PlatformFile, TruncatePlatformFile) { // Truncate the file. const int kTruncatedFileLength = 2; - EXPECT_TRUE(base::TruncatePlatformFile(file, kTruncatedFileLength)); + EXPECT_TRUE(file.Truncate(kTruncatedFileLength)); EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size)); EXPECT_EQ(kTruncatedFileLength, file_size); // Make sure the file was truncated. - bytes_read = ReadFully(file, 0, data_read, kTestDataSize); + bytes_read = file.Read(0, data_read, kTestDataSize); EXPECT_EQ(file_size, bytes_read); for (int i = 0; i < file_size; i++) EXPECT_EQ(data_to_write[i], data_read[i]); - - // Close the file handle to allow the temp directory to be deleted. - base::ClosePlatformFile(file); } // Flakily fails: http://crbug.com/86494 #if defined(OS_ANDROID) -TEST(PlatformFile, TouchGetInfoPlatformFile) { +TEST(File, TouchGetInfo) { #else -TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) { +TEST(File, DISABLED_TouchGetInfo) { #endif base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::PlatformFile file = base::CreatePlatformFile( - temp_dir.path().AppendASCII("touch_get_info_file"), - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE | - base::PLATFORM_FILE_WRITE_ATTRIBUTES, - NULL, - NULL); - EXPECT_NE(base::kInvalidPlatformFileValue, file); + File file(temp_dir.path().AppendASCII("touch_get_info_file"), + base::File::FLAG_CREATE | base::File::FLAG_WRITE | + base::File::FLAG_WRITE_ATTRIBUTES); + ASSERT_TRUE(file.IsValid()); // Get info for a newly created file. - base::PlatformFileInfo info; - EXPECT_TRUE(base::GetPlatformFileInfo(file, &info)); + base::File::Info info; + EXPECT_TRUE(file.GetInfo(&info)); // Add 2 seconds to account for possible rounding errors on // filesystems that use a 1s or 2s timestamp granularity. @@ -358,7 +296,7 @@ TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) { // Write "test" to the file. char data[] = "test"; const int kTestDataSize = 4; - int bytes_written = WriteFully(file, 0, data, kTestDataSize); + int bytes_written = file.Write(0, data, kTestDataSize); EXPECT_EQ(kTestDataSize, bytes_written); // Change the last_accessed and last_modified dates. @@ -370,11 +308,10 @@ TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) { base::Time new_last_modified = info.last_modified + base::TimeDelta::FromMinutes(567); - EXPECT_TRUE(base::TouchPlatformFile(file, new_last_accessed, - new_last_modified)); + EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified)); // Make sure the file info was updated accordingly. - EXPECT_TRUE(base::GetPlatformFileInfo(file, &info)); + EXPECT_TRUE(file.GetInfo(&info)); EXPECT_EQ(info.size, kTestDataSize); EXPECT_FALSE(info.is_directory); EXPECT_FALSE(info.is_symbolic_link); @@ -394,41 +331,30 @@ TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) { EXPECT_EQ(info.creation_time.ToInternalValue(), creation_time.ToInternalValue()); - - // Close the file handle to allow the temp directory to be deleted. - base::ClosePlatformFile(file); } -TEST(PlatformFile, ReadFileAtCurrentPosition) { +TEST(File, ReadFileAtCurrentPosition) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath file_path = temp_dir.path().AppendASCII("read_file_at_current_position"); - base::PlatformFile file = base::CreatePlatformFile( - file_path, - base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_WRITE, - NULL, NULL); - EXPECT_NE(base::kInvalidPlatformFileValue, file); + File file(file_path, + base::File::FLAG_CREATE | base::File::FLAG_READ | + base::File::FLAG_WRITE); + EXPECT_TRUE(file.IsValid()); const char kData[] = "test"; const int kDataSize = arraysize(kData) - 1; - EXPECT_EQ(kDataSize, WriteFully(file, 0, kData, kDataSize)); + EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize)); - EXPECT_EQ(0, SeekPlatformFile( - file, base::PLATFORM_FILE_FROM_BEGIN, 0)); + EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0)); char buffer[kDataSize]; int first_chunk_size = kDataSize / 2; - EXPECT_EQ(first_chunk_size, - base::ReadPlatformFileAtCurrentPos( - file, buffer, first_chunk_size)); + EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size)); EXPECT_EQ(kDataSize - first_chunk_size, - base::ReadPlatformFileAtCurrentPos( - file, buffer + first_chunk_size, - kDataSize - first_chunk_size)); + file.ReadAtCurrentPos(buffer + first_chunk_size, + kDataSize - first_chunk_size)); EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData)); - - base::ClosePlatformFile(file); } diff --git a/base/files/file_win.cc b/base/files/file_win.cc index 07b5c48..94f4d7f 100644 --- a/base/files/file_win.cc +++ b/base/files/file_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/platform_file.h" +#include "base/files/file.h" #include <io.h> @@ -12,129 +12,121 @@ #include "base/threading/thread_restrictions.h" namespace base { -PlatformFile CreatePlatformFileUnsafe(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error) { + +void File::CreateBaseFileUnsafe(const FilePath& name, uint32 flags) { base::ThreadRestrictions::AssertIOAllowed(); + DCHECK(!IsValid()); DWORD disposition = 0; - if (created) - *created = false; - if (flags & PLATFORM_FILE_OPEN) + if (flags & FLAG_OPEN) disposition = OPEN_EXISTING; - if (flags & PLATFORM_FILE_CREATE) { + if (flags & FLAG_CREATE) { DCHECK(!disposition); disposition = CREATE_NEW; } - if (flags & PLATFORM_FILE_OPEN_ALWAYS) { + if (flags & FLAG_OPEN_ALWAYS) { DCHECK(!disposition); disposition = OPEN_ALWAYS; } - if (flags & PLATFORM_FILE_CREATE_ALWAYS) { + if (flags & FLAG_CREATE_ALWAYS) { DCHECK(!disposition); disposition = CREATE_ALWAYS; } - if (flags & PLATFORM_FILE_OPEN_TRUNCATED) { + if (flags & FLAG_OPEN_TRUNCATED) { DCHECK(!disposition); - DCHECK(flags & PLATFORM_FILE_WRITE); + DCHECK(flags & FLAG_WRITE); disposition = TRUNCATE_EXISTING; } if (!disposition) { NOTREACHED(); - return NULL; + return; } DWORD access = 0; - if (flags & PLATFORM_FILE_WRITE) + if (flags & FLAG_WRITE) access = GENERIC_WRITE; - if (flags & PLATFORM_FILE_APPEND) { + if (flags & FLAG_APPEND) { DCHECK(!access); access = FILE_APPEND_DATA; } - if (flags & PLATFORM_FILE_READ) + if (flags & FLAG_READ) access |= GENERIC_READ; - if (flags & PLATFORM_FILE_WRITE_ATTRIBUTES) + if (flags & FLAG_WRITE_ATTRIBUTES) access |= FILE_WRITE_ATTRIBUTES; - if (flags & PLATFORM_FILE_EXECUTE) + if (flags & FLAG_EXECUTE) access |= GENERIC_EXECUTE; - DWORD sharing = (flags & PLATFORM_FILE_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ; - if (!(flags & PLATFORM_FILE_EXCLUSIVE_WRITE)) + DWORD sharing = (flags & FLAG_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ; + if (!(flags & FLAG_EXCLUSIVE_WRITE)) sharing |= FILE_SHARE_WRITE; - if (flags & PLATFORM_FILE_SHARE_DELETE) + if (flags & FLAG_SHARE_DELETE) sharing |= FILE_SHARE_DELETE; DWORD create_flags = 0; - if (flags & PLATFORM_FILE_ASYNC) + if (flags & FLAG_ASYNC) create_flags |= FILE_FLAG_OVERLAPPED; - if (flags & PLATFORM_FILE_TEMPORARY) + if (flags & FLAG_TEMPORARY) create_flags |= FILE_ATTRIBUTE_TEMPORARY; - if (flags & PLATFORM_FILE_HIDDEN) + if (flags & FLAG_HIDDEN) create_flags |= FILE_ATTRIBUTE_HIDDEN; - if (flags & PLATFORM_FILE_DELETE_ON_CLOSE) + if (flags & FLAG_DELETE_ON_CLOSE) create_flags |= FILE_FLAG_DELETE_ON_CLOSE; - if (flags & PLATFORM_FILE_BACKUP_SEMANTICS) + if (flags & FLAG_BACKUP_SEMANTICS) create_flags |= FILE_FLAG_BACKUP_SEMANTICS; - HANDLE file = CreateFile(name.value().c_str(), access, sharing, NULL, - disposition, create_flags, NULL); + file_.Set(CreateFile(name.value().c_str(), access, sharing, NULL, + disposition, create_flags, NULL)); - if (created && (INVALID_HANDLE_VALUE != file)) { - if (flags & (PLATFORM_FILE_OPEN_ALWAYS)) - *created = (ERROR_ALREADY_EXISTS != GetLastError()); - else if (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)) - *created = true; - } + if (file_.IsValid()) { + error_ = FILE_OK; + async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC); - if (error) { - if (file != kInvalidPlatformFileValue) - *error = PLATFORM_FILE_OK; - else - *error = LastErrorToPlatformFileError(GetLastError()); + if (flags & (FLAG_OPEN_ALWAYS)) + created_ = (ERROR_ALREADY_EXISTS != GetLastError()); + else if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)) + created_ = true; + } else { + error_ = OSErrorToFileError(GetLastError()); } - - return file; } -FILE* FdopenPlatformFile(PlatformFile file, const char* mode) { - if (file == kInvalidPlatformFileValue) - return NULL; - int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0); - if (fd < 0) - return NULL; - return _fdopen(fd, mode); +bool File::IsValid() const { + return file_.IsValid(); +} +PlatformFile File::TakePlatformFile() { + return file_.Take(); } -bool ClosePlatformFile(PlatformFile file) { +void File::Close() { base::ThreadRestrictions::AssertIOAllowed(); - return (CloseHandle(file) != 0); + file_.Close(); } -int64 SeekPlatformFile(PlatformFile file, - PlatformFileWhence whence, - int64 offset) { +int64 File::Seek(Whence whence, int64 offset) { base::ThreadRestrictions::AssertIOAllowed(); - if (file == kInvalidPlatformFileValue || offset < 0) + DCHECK(IsValid()); + if (offset < 0) return -1; LARGE_INTEGER distance, res; distance.QuadPart = offset; DWORD move_method = static_cast<DWORD>(whence); - if (!SetFilePointerEx(file, distance, &res, move_method)) + if (!SetFilePointerEx(file_, distance, &res, move_method)) return -1; return res.QuadPart; } -int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { +int File::Read(int64 offset, char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file == kInvalidPlatformFileValue || size < 0) + DCHECK(IsValid()); + DCHECK(!async_); + if (size < 0) return -1; LARGE_INTEGER offset_li; @@ -145,7 +137,7 @@ int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { overlapped.OffsetHigh = offset_li.HighPart; DWORD bytes_read; - if (::ReadFile(file, data, size, &bytes_read, &overlapped) != 0) + if (::ReadFile(file_, data, size, &bytes_read, &overlapped) != 0) return bytes_read; if (ERROR_HANDLE_EOF == GetLastError()) return 0; @@ -153,13 +145,15 @@ int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) { return -1; } -int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) { +int File::ReadAtCurrentPos(char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file == kInvalidPlatformFileValue || size < 0) + DCHECK(IsValid()); + DCHECK(!async_); + if (size < 0) return -1; DWORD bytes_read; - if (::ReadFile(file, data, size, &bytes_read, NULL) != 0) + if (::ReadFile(file_, data, size, &bytes_read, NULL) != 0) return bytes_read; if (ERROR_HANDLE_EOF == GetLastError()) return 0; @@ -167,21 +161,18 @@ int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) { return -1; } -int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, char* data, - int size) { - return ReadPlatformFile(file, offset, data, size); +int File::ReadNoBestEffort(int64 offset, char* data, int size) { + return Read(offset, data, size); } -int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, - char* data, int size) { - return ReadPlatformFileAtCurrentPos(file, data, size); +int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { + return ReadAtCurrentPos(data, size); } -int WritePlatformFile(PlatformFile file, int64 offset, - const char* data, int size) { +int File::Write(int64 offset, const char* data, int size) { base::ThreadRestrictions::AssertIOAllowed(); - if (file == kInvalidPlatformFileValue) - return -1; + DCHECK(IsValid()); + DCHECK(!async_); LARGE_INTEGER offset_li; offset_li.QuadPart = offset; @@ -191,72 +182,68 @@ int WritePlatformFile(PlatformFile file, int64 offset, overlapped.OffsetHigh = offset_li.HighPart; DWORD bytes_written; - if (::WriteFile(file, data, size, &bytes_written, &overlapped) != 0) + if (::WriteFile(file_, data, size, &bytes_written, &overlapped) != 0) return bytes_written; return -1; } -int WritePlatformFileAtCurrentPos(PlatformFile file, const char* data, - int size) { - return WritePlatformFile(file, 0, data, size); +int File::WriteAtCurrentPos(const char* data, int size) { + NOTREACHED(); + return -1; } -int WritePlatformFileCurPosNoBestEffort(PlatformFile file, - const char* data, int size) { - return WritePlatformFile(file, 0, data, size); +int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { + return WriteAtCurrentPos(data, size); } -bool TruncatePlatformFile(PlatformFile file, int64 length) { +bool File::Truncate(int64 length) { base::ThreadRestrictions::AssertIOAllowed(); - if (file == kInvalidPlatformFileValue) - return false; + DCHECK(IsValid()); // Get the current file pointer. LARGE_INTEGER file_pointer; LARGE_INTEGER zero; zero.QuadPart = 0; - if (::SetFilePointerEx(file, zero, &file_pointer, FILE_CURRENT) == 0) + if (::SetFilePointerEx(file_, zero, &file_pointer, FILE_CURRENT) == 0) return false; LARGE_INTEGER length_li; length_li.QuadPart = length; // If length > file size, SetFilePointerEx() should extend the file // with zeroes on all Windows standard file systems (NTFS, FATxx). - if (!::SetFilePointerEx(file, length_li, NULL, FILE_BEGIN)) + if (!::SetFilePointerEx(file_, length_li, NULL, FILE_BEGIN)) return false; // Set the new file length and move the file pointer to its old position. // This is consistent with ftruncate()'s behavior, even when the file // pointer points to a location beyond the end of the file. - return ((::SetEndOfFile(file) != 0) && - (::SetFilePointerEx(file, file_pointer, NULL, FILE_BEGIN) != 0)); + return ((::SetEndOfFile(file_) != 0) && + (::SetFilePointerEx(file_, file_pointer, NULL, FILE_BEGIN) != 0)); } -bool FlushPlatformFile(PlatformFile file) { +bool File::Flush() { base::ThreadRestrictions::AssertIOAllowed(); - return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file)); + DCHECK(IsValid()); + return ::FlushFileBuffers(file_) != FALSE; } -bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time, - const base::Time& last_modified_time) { +bool File::SetTimes(Time last_access_time, Time last_modified_time) { base::ThreadRestrictions::AssertIOAllowed(); - if (file == kInvalidPlatformFileValue) - return false; + DCHECK(IsValid()); FILETIME last_access_filetime = last_access_time.ToFileTime(); FILETIME last_modified_filetime = last_modified_time.ToFileTime(); - return (::SetFileTime(file, NULL, &last_access_filetime, + return (::SetFileTime(file_, NULL, &last_access_filetime, &last_modified_filetime) != 0); } -bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { +bool File::GetInfo(Info* info) { base::ThreadRestrictions::AssertIOAllowed(); - if (!info) - return false; + DCHECK(IsValid()); BY_HANDLE_FILE_INFORMATION file_info; - if (GetFileInformationByHandle(file, &file_info) == 0) + if (GetFileInformationByHandle(file_, &file_info) == 0) return false; LARGE_INTEGER size; @@ -265,61 +252,68 @@ bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { info->size = size.QuadPart; info->is_directory = (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - info->is_symbolic_link = false; // Windows doesn't have symbolic links. + info->is_symbolic_link = false; // Windows doesn't have symbolic links. info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime); info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime); info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime); return true; } -PlatformFileError LockPlatformFile(PlatformFile file) { - BOOL result = LockFile(file, 0, 0, MAXDWORD, MAXDWORD); +File::Error base::File::Lock() { + DCHECK(IsValid()); + BOOL result = LockFile(file_, 0, 0, MAXDWORD, MAXDWORD); if (!result) - return LastErrorToPlatformFileError(GetLastError()); - return PLATFORM_FILE_OK; + return OSErrorToFileError(GetLastError()); + return FILE_OK; } -PlatformFileError UnlockPlatformFile(PlatformFile file) { - BOOL result = UnlockFile(file, 0, 0, MAXDWORD, MAXDWORD); +File::Error File::Unlock() { + DCHECK(IsValid()); + BOOL result = UnlockFile(file_, 0, 0, MAXDWORD, MAXDWORD); if (!result) - return LastErrorToPlatformFileError(GetLastError()); - return PLATFORM_FILE_OK; + return OSErrorToFileError(GetLastError()); + return FILE_OK; } -PlatformFileError LastErrorToPlatformFileError(DWORD last_error) { +// Static. +File::Error File::OSErrorToFileError(DWORD last_error) { switch (last_error) { case ERROR_SHARING_VIOLATION: - return PLATFORM_FILE_ERROR_IN_USE; + return FILE_ERROR_IN_USE; case ERROR_FILE_EXISTS: - return PLATFORM_FILE_ERROR_EXISTS; + return FILE_ERROR_EXISTS; case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: - return PLATFORM_FILE_ERROR_NOT_FOUND; + return FILE_ERROR_NOT_FOUND; case ERROR_ACCESS_DENIED: - return PLATFORM_FILE_ERROR_ACCESS_DENIED; + return FILE_ERROR_ACCESS_DENIED; case ERROR_TOO_MANY_OPEN_FILES: - return PLATFORM_FILE_ERROR_TOO_MANY_OPENED; + return FILE_ERROR_TOO_MANY_OPENED; case ERROR_OUTOFMEMORY: case ERROR_NOT_ENOUGH_MEMORY: - return PLATFORM_FILE_ERROR_NO_MEMORY; + return FILE_ERROR_NO_MEMORY; case ERROR_HANDLE_DISK_FULL: case ERROR_DISK_FULL: case ERROR_DISK_RESOURCES_EXHAUSTED: - return PLATFORM_FILE_ERROR_NO_SPACE; + return FILE_ERROR_NO_SPACE; case ERROR_USER_MAPPED_FILE: - return PLATFORM_FILE_ERROR_INVALID_OPERATION; + return FILE_ERROR_INVALID_OPERATION; case ERROR_NOT_READY: case ERROR_SECTOR_NOT_FOUND: case ERROR_DEV_NOT_EXIST: case ERROR_IO_DEVICE: case ERROR_FILE_CORRUPT: case ERROR_DISK_CORRUPT: - return PLATFORM_FILE_ERROR_IO; + return FILE_ERROR_IO; default: UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows", last_error); - return PLATFORM_FILE_ERROR_FAILED; + return FILE_ERROR_FAILED; } } +void File::SetPlatformFile(PlatformFile file) { + file_.Set(file); +} + } // namespace base |