0

Begin the first small step towards using FilePath everywhere:

- Add some transition APIs.
- Start migrating some code to transition APIs.

Review URL: http://codereview.chromium.org/8825


git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4254 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
evanm@google.com
2008-10-30 23:54:04 +00:00
parent f92ed219c9
commit 640517fdd2
18 changed files with 476 additions and 313 deletions

@ -4,6 +4,7 @@
#include "base/base_paths.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
@ -12,15 +13,15 @@ namespace base {
bool PathProvider(int key, std::wstring* result) {
// NOTE: DIR_CURRENT is a special cased in PathService::Get
std::wstring cur;
FilePath cur;
switch (key) {
case base::DIR_EXE:
PathService::Get(base::FILE_EXE, &cur);
file_util::TrimFilename(&cur);
cur = cur.DirName();
break;
case base::DIR_MODULE:
PathService::Get(base::FILE_MODULE, &cur);
file_util::TrimFilename(&cur);
cur = cur.DirName();
break;
case base::DIR_TEMP:
if (!file_util::GetTempDir(&cur))
@ -30,7 +31,7 @@ bool PathProvider(int key, std::wstring* result) {
return false;
}
result->swap(cur);
*result = cur.ToWStringHack();
return true;
}

@ -6,6 +6,7 @@
#include <unistd.h>
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
@ -15,7 +16,7 @@
namespace base {
bool PathProviderLinux(int key, std::wstring* result) {
std::wstring cur;
FilePath path;
switch (key) {
case base::FILE_EXE:
case base::FILE_MODULE: { // TODO(evanm): is this correct?
@ -32,10 +33,11 @@ bool PathProviderLinux(int key, std::wstring* result) {
case base::DIR_SOURCE_ROOT:
// On linux, unit tests execute two levels deep from the source root.
// For example: chrome/{Debug|Hammer}/net_unittest
PathService::Get(base::DIR_EXE, &cur);
file_util::UpOneDirectory(&cur);
file_util::UpOneDirectory(&cur);
*result = cur;
if (!PathService::Get(base::DIR_EXE, &path))
return false;
path = path.Append(FilePath::kParentDirectory)
.Append(FilePath::kParentDirectory);
*result = path.ToWStringHack();
return true;
}
return false;

@ -4,6 +4,11 @@
#include "base/file_path.h"
// These includes are just for the *Hack functions, and should be removed
// when those functions are removed.
#include "base/string_piece.h"
#include "base/sys_string_conversions.h"
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
const FilePath::CharType FilePath::kSeparators[] = FILE_PATH_LITERAL("\\/");
#else // FILE_PATH_USES_WIN_SEPARATORS
@ -152,6 +157,29 @@ bool FilePath::IsAbsolute() const {
#endif // FILE_PATH_USES_DRIVE_LETTERS
}
#if defined(OS_POSIX)
// See file_path.h for a discussion of the encoding of paths on POSIX
// platforms. These *Hack() functions are not quite correct, but they're
// only temporary while we fix the remainder of the code.
// Remember to remove the #includes at the top when you remove these.
// static
FilePath FilePath::FromWStringHack(const std::wstring& wstring) {
return FilePath(base::SysWideToNativeMB(wstring));
}
std::wstring FilePath::ToWStringHack() const {
return base::SysNativeMBToWide(path_);
}
#elif defined(OS_WIN)
// static
FilePath FilePath::FromWStringHack(const std::wstring& wstring) {
return FilePath(wstring);
}
std::wstring FilePath::ToWStringHack() const {
return path_;
}
#endif
void FilePath::StripTrailingSeparators() {
// If there is no drive letter, start will be 1, which will prevent stripping
// the leading separator if there is only one separator. If there is a drive

@ -145,6 +145,20 @@ class FilePath {
// platforms, an absolute path begins with a separator character.
bool IsAbsolute() const;
// Older Chromium code assumes that paths are always wstrings.
// This function converts a wstring to a FilePath, and is useful to smooth
// porting that old code to the FilePath API.
// It has "Hack" in its name so people feel bad about using it.
// TODO(port): remove these functions.
static FilePath FromWStringHack(const std::wstring& wstring);
// Older Chromium code assumes that paths are always wstrings.
// This function produces a wstring from a FilePath, and is useful to smooth
// porting that old code to the FilePath API.
// It has "Hack" in its name so people feel bad about using it.
// TODO(port): remove these functions.
std::wstring ToWStringHack() const;
private:
// If this FilePath contains a drive letter specification, returns the
// position of the last character of the drive letter specification,

@ -8,6 +8,7 @@
#include <fstream>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "unicode/uniset.h"
@ -229,20 +230,14 @@ void ReplaceExtension(std::wstring* file_name, const std::wstring& extension) {
file_name->swap(result);
}
bool ContentsEqual(const std::wstring& filename1,
const std::wstring& filename2) {
bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
// We open the file in binary format even if they are text files because
// we are just comparing that bytes are exactly same in both files and not
// doing anything smart with text formatting.
#if defined(OS_WIN)
std::ifstream file1(filename1.c_str(), std::ios::in | std::ios::binary);
std::ifstream file2(filename2.c_str(), std::ios::in | std::ios::binary);
#elif defined(OS_POSIX)
std::ifstream file1(WideToUTF8(filename1).c_str(),
std::ifstream file1(filename1.value().c_str(),
std::ios::in | std::ios::binary);
std::ifstream file2(WideToUTF8(filename2).c_str(),
std::ifstream file2(filename2.value().c_str(),
std::ios::in | std::ios::binary);
#endif
// Even if both files aren't openable (and thus, in some sense, "equal"),
// any unusable file yields a result of "false".
@ -300,5 +295,60 @@ bool CloseFile(FILE* file) {
return fclose(file) == 0;
}
// Deprecated functions ----------------------------------------------------
bool AbsolutePath(std::wstring* path_str) {
FilePath path;
if (!AbsolutePath(&path))
return false;
*path_str = path.ToWStringHack();
return true;
}
bool Delete(const std::wstring& path, bool recursive) {
return Delete(FilePath::FromWStringHack(path), recursive);
}
bool Move(const std::wstring& from_path, const std::wstring& to_path) {
return Move(FilePath::FromWStringHack(from_path),
FilePath::FromWStringHack(to_path));
}
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
return CopyFile(FilePath::FromWStringHack(from_path),
FilePath::FromWStringHack(to_path));
}
bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
bool recursive) {
return CopyDirectory(FilePath::FromWStringHack(from_path),
FilePath::FromWStringHack(to_path),
recursive);
}
bool PathExists(const std::wstring& path) {
return PathExists(FilePath::FromWStringHack(path));
}
bool DirectoryExists(const std::wstring& path) {
return DirectoryExists(FilePath::FromWStringHack(path));
}
bool ContentsEqual(const std::wstring& filename1,
const std::wstring& filename2) {
return ContentsEqual(FilePath::FromWStringHack(filename1),
FilePath::FromWStringHack(filename2));
}
bool CreateDirectory(const std::wstring& full_path) {
return CreateDirectory(FilePath::FromWStringHack(full_path));
}
bool GetCurrentDirectory(std::wstring* path_str) {
FilePath path;
if (!GetCurrentDirectory(&path))
return false;
*path_str = path.ToWStringHack();
return true;
}
bool GetTempDir(std::wstring* path_str) {
FilePath path;
if (!GetTempDir(&path))
return false;
*path_str = path.ToWStringHack();
return true;
}
} // namespace

@ -24,6 +24,8 @@
#include "base/basictypes.h"
class FilePath;
namespace file_util {
//-----------------------------------------------------------------------------
@ -83,6 +85,8 @@ void AppendToPath(std::wstring* path, const std::wstring& new_ending);
// Convert provided relative path into an absolute path. Returns false on
// error.
bool AbsolutePath(FilePath* path);
// Deprecated temporary compatibility function.
bool AbsolutePath(std::wstring* path);
// Inserts |suffix| after the file name portion of |path| but before the
@ -127,13 +131,19 @@ int CountFilesCreatedAfter(const std::wstring& path,
//
// WARNING: USING THIS WITH recursive==true IS EQUIVALENT
// TO "rm -rf", SO USE WITH CAUTION.
bool Delete(const FilePath& path, bool recursive);
// Deprecated temporary compatibility function.
bool Delete(const std::wstring& path, bool recursive);
// Moves the given path, whether it's a file or a directory.
// Returns true if successful, false otherwise.
bool Move(const FilePath& from_path, const FilePath& to_path);
// Deprecated temporary compatibility function.
bool Move(const std::wstring& from_path, const std::wstring& to_path);
// Copies a single file. Use CopyDirectory to copy directories.
bool CopyFile(const FilePath& from_path, const FilePath& to_path);
// Deprecated temporary compatibility function.
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path);
// Copies the given path, and optionally all subdirectories and their contents
@ -143,17 +153,24 @@ bool CopyFile(const std::wstring& from_path, const std::wstring& to_path);
// Dont't use wildcards on the names, it may stop working without notice.
//
// If you only need to copy a file use CopyFile, it's faster.
bool CopyDirectory(const FilePath& from_path, const FilePath& to_path,
bool recursive);
// Deprecated temporary compatibility function.
bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
bool recursive);
// Returns true if the given path exists on the local filesystem,
// false otherwise.
bool PathExists(const FilePath& path);
// Deprecated temporary compatibility function.
bool PathExists(const std::wstring& path);
// Returns true if the given path is writable by the user, false otherwise.
bool PathIsWritable(const std::wstring& path);
// Returns true if the given path exists and is a directory, false otherwise.
bool DirectoryExists(const FilePath& path);
// Deprecated temporary compatibility function.
bool DirectoryExists(const std::wstring& path);
#if defined(OS_WIN)
@ -170,6 +187,9 @@ bool GetFileCreationLocalTimeFromHandle(HANDLE file_handle,
// Returns true if the contents of the two files given are equal, false
// otherwise. If either file can't be read, returns false.
bool ContentsEqual(const FilePath& filename1,
const FilePath& filename2);
// Deprecated temporary compatibility function.
bool ContentsEqual(const std::wstring& filename1,
const std::wstring& filename2);
@ -216,6 +236,8 @@ bool IsDirectoryEmpty(const std::wstring& dir_path);
// Get the temporary directory provided by the system.
bool GetTempDir(FilePath* path);
// Deprecated temporary compatibility function.
bool GetTempDir(std::wstring* path);
// Creates a temporary file. The full path is placed in 'temp_file', and the
@ -237,6 +259,8 @@ bool CreateNewTempDirectory(const std::wstring& prefix,
// Creates a directory, as well as creating any parent directories, if they
// don't exist. Returns 'true' on successful creation, or if the directory
// already exists.
bool CreateDirectory(const FilePath& full_path);
// Deprecated temporary compatibility function.
bool CreateDirectory(const std::wstring& full_path);
// Returns the file size. Returns true on success.
@ -257,6 +281,8 @@ struct FileInfo {
bool GetFileInfo(const std::wstring& file_path, FileInfo* info);
// Wrapper for fopen-like calls. Returns non-NULL FILE* on success.
FILE* OpenFile(const FilePath& filename, const char* mode);
// Deprecated temporary compatibility functions.
FILE* OpenFile(const std::string& filename, const char* mode);
FILE* OpenFile(const std::wstring& filename, const char* mode);
@ -272,6 +298,8 @@ int ReadFile(const std::wstring& filename, char* data, int size);
int WriteFile(const std::wstring& filename, const char* data, int size);
// Gets the current working directory for the process.
bool GetCurrentDirectory(FilePath* path);
// Deprecated temporary compatibility function.
bool GetCurrentDirectory(std::wstring* path);
// Sets the current working directory for the process.

@ -9,6 +9,7 @@
#include <string>
#include <vector>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
@ -16,21 +17,21 @@ namespace file_util {
const wchar_t kPathSeparator = L'/';
bool GetTempDir(std::wstring* path) {
bool GetTempDir(FilePath* path) {
const char* tmp = getenv("TMPDIR");
if (tmp)
*path = UTF8ToWide(tmp);
*path = FilePath(tmp);
else
*path = L"/tmp";
*path = FilePath("/tmp");
return true;
}
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
int infile = open(WideToUTF8(from_path).c_str(), O_RDONLY);
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
int infile = open(from_path.value().c_str(), O_RDONLY);
if (infile < 0)
return false;
int outfile = creat(WideToUTF8(to_path).c_str(), 0666);
int outfile = creat(to_path.value().c_str(), 0666);
if (outfile < 0) {
close(infile);
return false;

@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h>
#include <copyfile.h>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
@ -14,18 +15,17 @@ namespace file_util {
const wchar_t kPathSeparator = L'/';
bool GetTempDir(std::wstring* path) {
bool GetTempDir(FilePath* path) {
NSString* tmp = NSTemporaryDirectory();
if (tmp == nil)
return false;
*path = reinterpret_cast<const wchar_t*>(
[tmp cStringUsingEncoding:NSUTF32StringEncoding]);
*path = FilePath([tmp fileSystemRepresentation]);
return true;
}
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
return (copyfile(WideToUTF8(from_path).c_str(),
WideToUTF8(to_path).c_str(), NULL, COPYFILE_ALL) == 0);
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
return (copyfile(from_path.value().c_str(),
to_path.value().c_str(), NULL, COPYFILE_ALL) == 0);
}
} // namespace

@ -18,6 +18,7 @@
#include <fstream>
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/string_util.h"
@ -37,11 +38,11 @@ std::wstring GetDirectoryFromPath(const std::wstring& path) {
}
}
bool AbsolutePath(std::wstring* path) {
bool AbsolutePath(FilePath* path) {
char full_path[PATH_MAX];
if (realpath(WideToUTF8(*path).c_str(), full_path) == NULL)
if (realpath(path->value().c_str(), full_path) == NULL)
return false;
*path = UTF8ToWide(full_path);
*path = FilePath(full_path);
return true;
}
@ -49,25 +50,24 @@ bool AbsolutePath(std::wstring* path) {
// which works both with and without the recursive flag. I'm not sure we need
// that functionality. If not, remove from file_util_win.cc, otherwise add it
// here.
bool Delete(const std::wstring& path, bool recursive) {
std::string utf8_path_string = WideToUTF8(path);
const char* utf8_path = utf8_path_string.c_str();
bool Delete(const FilePath& path, bool recursive) {
const char* path_str = path.value().c_str();
struct stat64 file_info;
int test = stat64(utf8_path, &file_info);
int test = stat64(path_str, &file_info);
if (test != 0) {
// The Windows version defines this condition as success.
bool ret = (errno == ENOENT || errno == ENOTDIR);
return ret;
}
if (!S_ISDIR(file_info.st_mode))
return (unlink(utf8_path) == 0);
return (unlink(path_str) == 0);
if (!recursive)
return (rmdir(utf8_path) == 0);
return (rmdir(path_str) == 0);
bool success = true;
int ftsflags = FTS_PHYSICAL | FTS_NOSTAT;
char top_dir[PATH_MAX];
if (base::strlcpy(top_dir, utf8_path,
if (base::strlcpy(top_dir, path_str,
arraysize(top_dir)) >= arraysize(top_dir)) {
return false;
}
@ -105,26 +105,23 @@ bool Delete(const std::wstring& path, bool recursive) {
return success;
}
bool Move(const std::wstring& from_path, const std::wstring& to_path) {
return (rename(WideToUTF8(from_path).c_str(),
WideToUTF8(to_path).c_str()) == 0);
bool Move(const FilePath& from_path, const FilePath& to_path) {
return (rename(from_path.value().c_str(),
to_path.value().c_str()) == 0);
}
bool CopyDirectory(const std::wstring& from_path_wide,
const std::wstring& to_path_wide,
bool CopyDirectory(const FilePath& from_path,
const FilePath& to_path,
bool recursive) {
const std::string to_path = WideToUTF8(to_path_wide);
const std::string from_path = WideToUTF8(from_path_wide);
// Some old callers of CopyDirectory want it to support wildcards.
// After some discussion, we decided to fix those callers.
// Break loudly here if anyone tries to do this.
// TODO(evanm): remove this once we're sure it's ok.
DCHECK(to_path.find('*') == std::string::npos);
DCHECK(from_path.find('*') == std::string::npos);
DCHECK(to_path.value().find('*') == std::string::npos);
DCHECK(from_path.value().find('*') == std::string::npos);
char top_dir[PATH_MAX];
if (base::strlcpy(top_dir, from_path.c_str(),
if (base::strlcpy(top_dir, from_path.value().c_str(),
arraysize(top_dir)) >= arraysize(top_dir)) {
return false;
}
@ -141,7 +138,8 @@ bool CopyDirectory(const std::wstring& from_path_wide,
while (!error && (ent = fts_read(fts)) != NULL) {
// ent->fts_path is the source path, including from_path, so paste
// the suffix after from_path onto to_path to create the target_path.
const std::string target_path = to_path + &ent->fts_path[from_path.size()];
const std::string target_path =
to_path.value() + &ent->fts_path[from_path.value().size()];
switch (ent->fts_info) {
case FTS_D: // Preorder directory.
// If we encounter a subdirectory in a non-recursive copy, prune it
@ -211,14 +209,14 @@ bool CopyDirectory(const std::wstring& from_path_wide,
return true;
}
bool PathExists(const std::wstring& path) {
bool PathExists(const FilePath& path) {
struct stat64 file_info;
return (stat64(WideToUTF8(path).c_str(), &file_info) == 0);
return (stat64(path.value().c_str(), &file_info) == 0);
}
bool DirectoryExists(const std::wstring& path) {
bool DirectoryExists(const FilePath& path) {
struct stat64 file_info;
if (stat64(WideToUTF8(path).c_str(), &file_info) == 0)
if (stat64(path.value().c_str(), &file_info) == 0)
return S_ISDIR(file_info.st_mode);
return false;
}
@ -290,18 +288,23 @@ bool CreateNewTempDirectory(const std::wstring& prefix,
return true;
}
bool CreateDirectory(const std::wstring& full_path) {
std::vector<std::wstring> components;
PathComponents(full_path, &components);
std::wstring path;
std::vector<std::wstring>::iterator i = components.begin();
for (; i != components.end(); ++i) {
if (path.length() == 0)
path = *i;
else
AppendToPath(&path, *i);
if (!DirectoryExists(path)) {
if (mkdir(WideToUTF8(path).c_str(), 0777) != 0)
bool CreateDirectory(const FilePath& full_path) {
std::vector<FilePath> subpaths;
// Collect a list of all parent directories.
FilePath last_path = full_path;
subpaths.push_back(full_path);
for (FilePath path = full_path.DirName();
path.value() != last_path.value(); path = path.DirName()) {
subpaths.push_back(path);
last_path = path;
}
// Iterate through the parents and create the missing ones.
for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
i != subpaths.rend(); ++i) {
if (!DirectoryExists(*i)) {
if (mkdir(i->value().c_str(), 0777) != 0)
return false;
}
}
@ -358,10 +361,13 @@ int WriteFile(const std::wstring& filename, const char* data, int size) {
}
// Gets the current working directory for the process.
bool GetCurrentDirectory(std::wstring* dir) {
bool GetCurrentDirectory(FilePath* dir) {
char system_buffer[PATH_MAX] = "";
getcwd(system_buffer, sizeof(system_buffer));
*dir = UTF8ToWide(system_buffer);
if (!getcwd(system_buffer, sizeof(system_buffer))) {
NOTREACHED();
return false;
}
*dir = FilePath(system_buffer);
return true;
}

@ -15,6 +15,7 @@
#include <set>
#include "base/base_paths.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
@ -32,11 +33,11 @@ class FileUtilTest : public PlatformTest {
PlatformTest::SetUp();
// Name a subdirectory of the temp directory.
ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
file_util::AppendToPath(&test_dir_, L"FileUtilTest");
test_dir_ = test_dir_.Append(FILE_PATH_LITERAL("FileUtilTest"));
// Create a fresh, empty copy of this directory.
file_util::Delete(test_dir_, true);
file_util::CreateDirectory(test_dir_.c_str());
file_util::CreateDirectory(test_dir_);
}
virtual void TearDown() {
PlatformTest::TearDown();
@ -46,7 +47,7 @@ class FileUtilTest : public PlatformTest {
}
// the path to temporary directory used to contain the test operations
std::wstring test_dir_;
FilePath test_dir_;
};
// Collects all the results from the given file enumerator, and provides an
@ -56,43 +57,44 @@ class FindResultCollector {
FindResultCollector(file_util::FileEnumerator& enumerator) {
std::wstring cur_file;
while (!(cur_file = enumerator.Next()).empty()) {
FilePath::StringType path = FilePath::FromWStringHack(cur_file).value();
// The file should not be returned twice.
EXPECT_TRUE(files_.end() == files_.find(cur_file))
EXPECT_TRUE(files_.end() == files_.find(path))
<< "Same file returned twice";
// Save for later.
files_.insert(cur_file);
files_.insert(path);
}
}
// Returns true if the enumerator found the file.
bool HasFile(const std::wstring& file) const {
return files_.find(file) != files_.end();
bool HasFile(const FilePath& file) const {
return files_.find(file.value()) != files_.end();
}
int size() {
return static_cast<int>(files_.size());
}
private:
std::set<std::wstring> files_;
std::set<FilePath::StringType> files_;
};
// Simple function to dump some text into a new file.
void CreateTextFile(const std::wstring& filename,
void CreateTextFile(const FilePath& filename,
const std::wstring& contents) {
std::ofstream file;
file.open(WideToUTF8(filename).c_str());
file.open(WideToUTF8(filename.ToWStringHack()).c_str());
ASSERT_TRUE(file.is_open());
file << contents;
file.close();
}
// Simple function to take out some text from a file.
std::wstring ReadTextFile(const std::wstring& filename) {
std::wstring ReadTextFile(const FilePath& filename) {
wchar_t contents[64];
std::wifstream file;
file.open(WideToUTF8(filename).c_str());
file.open(WideToUTF8(filename.ToWStringHack()).c_str());
EXPECT_TRUE(file.is_open());
file.getline(contents, 64);
file.close();
@ -310,8 +312,7 @@ TEST_F(FileUtilTest, GetDirectoryFromPath) {
#if defined OS_WIN
TEST_F(FileUtilTest, CountFilesCreatedAfter) {
// Create old file (that we don't want to count)
std::wstring old_file_name = test_dir_;
file_util::AppendToPath(&old_file_name, L"Old File.txt");
FilePath old_file_name = test_dir_.Append(L"Old File.txt");
CreateTextFile(old_file_name, L"Just call me Mr. Creakybits");
// Age to perfection
@ -320,19 +321,21 @@ TEST_F(FileUtilTest, CountFilesCreatedAfter) {
// Establish our cutoff time
FILETIME test_start_time;
GetSystemTimeAsFileTime(&test_start_time);
EXPECT_EQ(0, file_util::CountFilesCreatedAfter(test_dir_, test_start_time));
EXPECT_EQ(0, file_util::CountFilesCreatedAfter(test_dir_.value(),
test_start_time));
// Create a new file (that we do want to count)
std::wstring new_file_name = test_dir_;
file_util::AppendToPath(&new_file_name, L"New File.txt");
FilePath new_file_name = test_dir_.Append(L"New File.txt");
CreateTextFile(new_file_name, L"Waaaaaaaaaaaaaah.");
// We should see only the new file.
EXPECT_EQ(1, file_util::CountFilesCreatedAfter(test_dir_, test_start_time));
EXPECT_EQ(1, file_util::CountFilesCreatedAfter(test_dir_.value(),
test_start_time));
// Delete new file, we should see no files after cutoff now
EXPECT_TRUE(file_util::Delete(new_file_name, false));
EXPECT_EQ(0, file_util::CountFilesCreatedAfter(test_dir_, test_start_time));
EXPECT_EQ(0, file_util::CountFilesCreatedAfter(test_dir_.value(),
test_start_time));
}
#endif
@ -340,23 +343,20 @@ TEST_F(FileUtilTest, CountFilesCreatedAfter) {
// the recursion flag. Also coincidentally tests PathExists.
TEST_F(FileUtilTest, Delete) {
// Create a file
std::wstring file_name = test_dir_;
file_util::AppendToPath(&file_name, L"Test File.txt");
FilePath file_name = test_dir_.Append(FILE_PATH_LITERAL("Test File.txt"));
CreateTextFile(file_name, L"I'm cannon fodder.");
ASSERT_TRUE(file_util::PathExists(file_name));
std::wstring subdir_path = test_dir_;
file_util::AppendToPath(&subdir_path, L"Subdirectory");
file_util::CreateDirectory(subdir_path.c_str());
FilePath subdir_path = test_dir_.Append(FILE_PATH_LITERAL("Subdirectory"));
file_util::CreateDirectory(subdir_path);
ASSERT_TRUE(file_util::PathExists(subdir_path));
std::wstring directory_contents = test_dir_;
FilePath directory_contents = test_dir_;
#if defined(OS_WIN)
// TODO(erikkay): see if anyone's actually using this feature of the API
file_util::AppendToPath(&directory_contents, L"*");
directory_contents = directory_contents.Append(FILE_PATH_LITERAL("*"));
// Delete non-recursively and check that only the file is deleted
ASSERT_TRUE(file_util::Delete(directory_contents, false));
EXPECT_FALSE(file_util::PathExists(file_name));
@ -371,22 +371,21 @@ TEST_F(FileUtilTest, Delete) {
TEST_F(FileUtilTest, Move) {
// Create a directory
std::wstring dir_name_from(test_dir_);
file_util::AppendToPath(&dir_name_from, L"Move_From_Subdir");
file_util::CreateDirectory(dir_name_from.c_str());
FilePath dir_name_from =
test_dir_.Append(FILE_PATH_LITERAL("Move_From_Subdir"));
file_util::CreateDirectory(dir_name_from);
ASSERT_TRUE(file_util::PathExists(dir_name_from));
// Create a file under the directory
std::wstring file_name_from(dir_name_from);
file_util::AppendToPath(&file_name_from, L"Move_Test_File.txt");
FilePath file_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
ASSERT_TRUE(file_util::PathExists(file_name_from));
// Move the directory
std::wstring dir_name_to(test_dir_);
file_util::AppendToPath(&dir_name_to, L"Move_To_Subdir");
std::wstring file_name_to(dir_name_to);
file_util::AppendToPath(&file_name_to, L"Move_Test_File.txt");
FilePath dir_name_to = test_dir_.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
FilePath file_name_to =
dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
ASSERT_FALSE(file_util::PathExists(dir_name_to));
@ -401,38 +400,38 @@ TEST_F(FileUtilTest, Move) {
TEST_F(FileUtilTest, CopyDirectoryRecursively) {
// Create a directory.
std::wstring dir_name_from(test_dir_);
file_util::AppendToPath(&dir_name_from, L"Copy_From_Subdir");
file_util::CreateDirectory(dir_name_from.c_str());
FilePath dir_name_from =
test_dir_.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
file_util::CreateDirectory(dir_name_from);
ASSERT_TRUE(file_util::PathExists(dir_name_from));
// Create a file under the directory.
std::wstring file_name_from(dir_name_from);
file_util::AppendToPath(&file_name_from, L"Copy_Test_File.txt");
FilePath file_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
ASSERT_TRUE(file_util::PathExists(file_name_from));
// Create a subdirectory.
std::wstring subdir_name_from(dir_name_from);
file_util::AppendToPath(&subdir_name_from, L"Subdir");
file_util::CreateDirectory(subdir_name_from.c_str());
FilePath subdir_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
file_util::CreateDirectory(subdir_name_from);
ASSERT_TRUE(file_util::PathExists(subdir_name_from));
// Create a file under the subdirectory.
std::wstring file_name2_from(subdir_name_from);
file_util::AppendToPath(&file_name2_from, L"Copy_Test_File.txt");
FilePath file_name2_from =
subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
ASSERT_TRUE(file_util::PathExists(file_name2_from));
// Copy the directory recursively.
std::wstring dir_name_to(test_dir_);
file_util::AppendToPath(&dir_name_to, L"Copy_To_Subdir");
std::wstring file_name_to(dir_name_to);
file_util::AppendToPath(&file_name_to, L"Copy_Test_File.txt");
std::wstring subdir_name_to(dir_name_to);
file_util::AppendToPath(&subdir_name_to, L"Subdir");
std::wstring file_name2_to(subdir_name_to);
file_util::AppendToPath(&file_name2_to, L"Copy_Test_File.txt");
FilePath dir_name_to =
test_dir_.Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
FilePath file_name_to =
dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
FilePath subdir_name_to =
dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
FilePath file_name2_to =
subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
ASSERT_FALSE(file_util::PathExists(dir_name_to));
@ -451,36 +450,36 @@ TEST_F(FileUtilTest, CopyDirectoryRecursively) {
TEST_F(FileUtilTest, CopyDirectory) {
// Create a directory.
std::wstring dir_name_from(test_dir_);
file_util::AppendToPath(&dir_name_from, L"Copy_From_Subdir");
file_util::CreateDirectory(dir_name_from.c_str());
FilePath dir_name_from =
test_dir_.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
file_util::CreateDirectory(dir_name_from);
ASSERT_TRUE(file_util::PathExists(dir_name_from));
// Create a file under the directory.
std::wstring file_name_from(dir_name_from);
file_util::AppendToPath(&file_name_from, L"Copy_Test_File.txt");
FilePath file_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
ASSERT_TRUE(file_util::PathExists(file_name_from));
// Create a subdirectory.
std::wstring subdir_name_from(dir_name_from);
file_util::AppendToPath(&subdir_name_from, L"Subdir");
file_util::CreateDirectory(subdir_name_from.c_str());
FilePath subdir_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
file_util::CreateDirectory(subdir_name_from);
ASSERT_TRUE(file_util::PathExists(subdir_name_from));
// Create a file under the subdirectory.
std::wstring file_name2_from(subdir_name_from);
file_util::AppendToPath(&file_name2_from, L"Copy_Test_File.txt");
FilePath file_name2_from =
subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
ASSERT_TRUE(file_util::PathExists(file_name2_from));
// Copy the directory not recursively.
std::wstring dir_name_to(test_dir_);
file_util::AppendToPath(&dir_name_to, L"Copy_To_Subdir");
std::wstring file_name_to(dir_name_to);
file_util::AppendToPath(&file_name_to, L"Copy_Test_File.txt");
std::wstring subdir_name_to(dir_name_to);
file_util::AppendToPath(&subdir_name_to, L"Subdir");
FilePath dir_name_to =
test_dir_.Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
FilePath file_name_to =
dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
FilePath subdir_name_to =
dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
ASSERT_FALSE(file_util::PathExists(dir_name_to));
@ -498,29 +497,29 @@ TEST_F(FileUtilTest, CopyDirectory) {
TEST_F(FileUtilTest, CopyFile) {
// Create a directory
std::wstring dir_name_from(test_dir_);
file_util::AppendToPath(&dir_name_from, L"Copy_From_Subdir");
file_util::CreateDirectory(dir_name_from.c_str());
FilePath dir_name_from =
test_dir_.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
file_util::CreateDirectory(dir_name_from);
ASSERT_TRUE(file_util::PathExists(dir_name_from));
// Create a file under the directory
std::wstring file_name_from(dir_name_from);
file_util::AppendToPath(&file_name_from, L"Copy_Test_File.txt");
FilePath file_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
const std::wstring file_contents(L"Gooooooooooooooooooooogle");
CreateTextFile(file_name_from, file_contents);
ASSERT_TRUE(file_util::PathExists(file_name_from));
// Copy the file.
std::wstring dest_file(dir_name_from);
file_util::AppendToPath(&dest_file, L"DestFile.txt");
FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
ASSERT_TRUE(file_util::CopyFile(file_name_from, dest_file));
// Copy the file to another location using '..' in the path.
std::wstring dest_file2(dir_name_from);
std::wstring dest_file2(dir_name_from.ToWStringHack());
file_util::AppendToPath(&dest_file2, L"..");
file_util::AppendToPath(&dest_file2, L"DestFile.txt");
ASSERT_TRUE(file_util::CopyFile(file_name_from, dest_file2));
std::wstring dest_file2_test(dir_name_from);
ASSERT_TRUE(file_util::CopyFile(file_name_from,
FilePath::FromWStringHack(dest_file2)));
std::wstring dest_file2_test(dir_name_from.ToWStringHack());
file_util::UpOneDirectory(&dest_file2_test);
file_util::AppendToPath(&dest_file2_test, L"DestFile.txt");
@ -529,15 +528,15 @@ TEST_F(FileUtilTest, CopyFile) {
EXPECT_TRUE(file_util::PathExists(dest_file));
const std::wstring read_contents = ReadTextFile(dest_file);
EXPECT_EQ(file_contents, read_contents);
EXPECT_TRUE(file_util::PathExists(dest_file2_test));
EXPECT_TRUE(file_util::PathExists(dest_file2));
EXPECT_TRUE(file_util::PathExists(
FilePath::FromWStringHack(dest_file2_test)));
EXPECT_TRUE(file_util::PathExists(FilePath::FromWStringHack(dest_file2)));
}
// TODO(erikkay): implement
#if defined(OS_WIN)
TEST_F(FileUtilTest, GetFileCreationLocalTime) {
std::wstring file_name = test_dir_;
file_util::AppendToPath(&file_name, L"Test File.txt");
FilePath file_name = test_dir_.Append(L"Test File.txt");
SYSTEMTIME start_time;
GetLocalTime(&start_time);
@ -548,7 +547,7 @@ TEST_F(FileUtilTest, GetFileCreationLocalTime) {
GetLocalTime(&end_time);
SYSTEMTIME file_creation_time;
file_util::GetFileCreationLocalTime(file_name, &file_creation_time);
file_util::GetFileCreationLocalTime(file_name.value(), &file_creation_time);
FILETIME start_filetime;
SystemTimeToFileTime(&start_time, &start_filetime);
@ -565,46 +564,46 @@ TEST_F(FileUtilTest, GetFileCreationLocalTime) {
"creation time: " << FileTimeAsUint64(file_creation_filetime) << ", " <<
"end time: " << FileTimeAsUint64(end_filetime);
ASSERT_TRUE(DeleteFile(file_name.c_str()));
ASSERT_TRUE(DeleteFile(file_name.value().c_str()));
}
#endif
// file_util winds up using autoreleased objects on the Mac, so this needs
// to be a PlatformTest
// to be a PlatformTest.
typedef PlatformTest ReadOnlyFileUtilTest;
TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
std::wstring data_dir;
FilePath data_dir;
ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
file_util::AppendToPath(&data_dir, L"base");
file_util::AppendToPath(&data_dir, L"data");
file_util::AppendToPath(&data_dir, L"file_util_unittest");
data_dir = data_dir.Append(FILE_PATH_LITERAL("base"))
.Append(FILE_PATH_LITERAL("data"))
.Append(FILE_PATH_LITERAL("file_util_unittest"));
ASSERT_TRUE(file_util::PathExists(data_dir));
std::wstring original_file = data_dir;
file_util::AppendToPath(&original_file, L"original.txt");
std::wstring same_file = data_dir;
file_util::AppendToPath(&same_file, L"same.txt");
std::wstring same_length_file = data_dir;
file_util::AppendToPath(&same_length_file, L"same_length.txt");
std::wstring different_file = data_dir;
file_util::AppendToPath(&different_file, L"different.txt");
std::wstring different_first_file = data_dir;
file_util::AppendToPath(&different_first_file, L"different_first.txt");
std::wstring different_last_file = data_dir;
file_util::AppendToPath(&different_last_file, L"different_last.txt");
std::wstring empty1_file = data_dir;
file_util::AppendToPath(&empty1_file, L"empty1.txt");
std::wstring empty2_file = data_dir;
file_util::AppendToPath(&empty2_file, L"empty2.txt");
std::wstring shortened_file = data_dir;
file_util::AppendToPath(&shortened_file, L"shortened.txt");
std::wstring binary_file = data_dir;
file_util::AppendToPath(&binary_file, L"binary_file.bin");
std::wstring binary_file_same = data_dir;
file_util::AppendToPath(&binary_file_same, L"binary_file_same.bin");
std::wstring binary_file_diff = data_dir;
file_util::AppendToPath(&binary_file_diff, L"binary_file_diff.bin");
FilePath original_file =
data_dir.Append(FILE_PATH_LITERAL("original.txt"));
FilePath same_file =
data_dir.Append(FILE_PATH_LITERAL("same.txt"));
FilePath same_length_file =
data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
FilePath different_file =
data_dir.Append(FILE_PATH_LITERAL("different.txt"));
FilePath different_first_file =
data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
FilePath different_last_file =
data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
FilePath empty1_file =
data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
FilePath empty2_file =
data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
FilePath shortened_file =
data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
FilePath binary_file =
data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
FilePath binary_file_same =
data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
FilePath binary_file_diff =
data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
EXPECT_TRUE(file_util::ContentsEqual(original_file, original_file));
EXPECT_TRUE(file_util::ContentsEqual(original_file, same_file));
@ -623,12 +622,10 @@ TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
// We don't need equivalent functionality outside of Windows.
#if defined(OS_WIN)
TEST_F(FileUtilTest, ResolveShortcutTest) {
std::wstring target_file = test_dir_;
file_util::AppendToPath(&target_file, L"Target.txt");
FilePath target_file = test_dir_.Append(L"Target.txt");
CreateTextFile(target_file, L"This is the target.");
std::wstring link_file = test_dir_;
file_util::AppendToPath(&link_file, L"Link.lnk");
FilePath link_file = test_dir_.Append(L"Link.lnk");
HRESULT result;
IShellLink *shell = NULL;
@ -643,11 +640,11 @@ TEST_F(FileUtilTest, ResolveShortcutTest) {
result = shell->QueryInterface(IID_IPersistFile,
reinterpret_cast<LPVOID*>(&persist));
EXPECT_TRUE(SUCCEEDED(result));
result = shell->SetPath(target_file.c_str());
result = shell->SetPath(target_file.value().c_str());
EXPECT_TRUE(SUCCEEDED(result));
result = shell->SetDescription(L"ResolveShortcutTest");
EXPECT_TRUE(SUCCEEDED(result));
result = persist->Save(link_file.c_str(), TRUE);
result = persist->Save(link_file.value().c_str(), TRUE);
EXPECT_TRUE(SUCCEEDED(result));
if (persist)
persist->Release();
@ -655,38 +652,37 @@ TEST_F(FileUtilTest, ResolveShortcutTest) {
shell->Release();
bool is_solved;
is_solved = file_util::ResolveShortcut(&link_file);
std::wstring link_file_str = link_file.value();
is_solved = file_util::ResolveShortcut(&link_file_str);
EXPECT_TRUE(is_solved);
std::wstring contents;
contents = ReadTextFile(link_file);
contents = ReadTextFile(FilePath(link_file_str));
EXPECT_EQ(L"This is the target.", contents);
// Cleaning
DeleteFile(target_file.c_str());
DeleteFile(link_file.c_str());
DeleteFile(target_file.value().c_str());
DeleteFile(link_file_str.c_str());
CoUninitialize();
}
TEST_F(FileUtilTest, CreateShortcutTest) {
const wchar_t file_contents[] = L"This is another target.";
std::wstring target_file = test_dir_;
file_util::AppendToPath(&target_file, L"Target1.txt");
FilePath target_file = test_dir_.Append(L"Target1.txt");
CreateTextFile(target_file, file_contents);
std::wstring link_file = test_dir_;
file_util::AppendToPath(&link_file, L"Link1.lnk");
FilePath link_file = test_dir_.Append(L"Link1.lnk");
CoInitialize(NULL);
EXPECT_TRUE(file_util::CreateShortcutLink(target_file.c_str(),
link_file.c_str(),
EXPECT_TRUE(file_util::CreateShortcutLink(target_file.value().c_str(),
link_file.value().c_str(),
NULL, NULL, NULL, NULL, 0));
std::wstring resolved_name = link_file;
std::wstring resolved_name = link_file.value();
EXPECT_TRUE(file_util::ResolveShortcut(&resolved_name));
std::wstring read_contents = ReadTextFile(resolved_name);
std::wstring read_contents = ReadTextFile(FilePath(resolved_name));
EXPECT_EQ(file_contents, read_contents);
DeleteFile(target_file.c_str());
DeleteFile(link_file.c_str());
DeleteFile(target_file.value().c_str());
DeleteFile(link_file.value().c_str());
CoUninitialize();
}
#endif
@ -706,13 +702,14 @@ TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
}
TEST_F(FileUtilTest, CreateDirectoryTest) {
std::wstring test_root = test_dir_;
file_util::AppendToPath(&test_root, L"create_directory_test");
std::wstring test_path(test_root);
FilePath test_root =
test_dir_.Append(FILE_PATH_LITERAL("create_directory_test"));
#if defined(OS_WIN)
file_util::AppendToPath(&test_path, L"dir\\tree\\likely\\doesnt\\exist\\");
FilePath test_path =
test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
#elif defined(OS_POSIX)
file_util::AppendToPath(&test_path, L"dir/tree/likely/doesnt/exist/");
FilePath test_path =
test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
#endif
EXPECT_FALSE(file_util::PathExists(test_path));
@ -722,7 +719,7 @@ TEST_F(FileUtilTest, CreateDirectoryTest) {
EXPECT_TRUE(file_util::CreateDirectory(test_path));
// Doesn't work to create it on top of a non-dir
file_util::AppendToPath(&test_path, L"foobar.txt");
test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
EXPECT_FALSE(file_util::PathExists(test_path));
CreateTextFile(test_path, L"test file");
EXPECT_TRUE(file_util::PathExists(test_path));
@ -735,16 +732,16 @@ TEST_F(FileUtilTest, CreateDirectoryTest) {
TEST_F(FileUtilTest, DetectDirectoryTest) {
// Check a directory
std::wstring test_root = test_dir_;
file_util::AppendToPath(&test_root, L"detect_directory_test");
FilePath test_root =
test_dir_.Append(FILE_PATH_LITERAL("detect_directory_test"));
EXPECT_FALSE(file_util::PathExists(test_root));
EXPECT_TRUE(file_util::CreateDirectory(test_root));
EXPECT_TRUE(file_util::PathExists(test_root));
EXPECT_TRUE(file_util::DirectoryExists(test_root));
// Check a file
std::wstring test_path(test_root);
file_util::AppendToPath(&test_path, L"foobar.txt");
FilePath test_path =
test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
EXPECT_FALSE(file_util::PathExists(test_path));
CreateTextFile(test_path, L"test file");
EXPECT_TRUE(file_util::PathExists(test_path));
@ -833,41 +830,34 @@ TEST_F(FileUtilTest, ReplaceExtensionTestWithPathSeparators) {
TEST_F(FileUtilTest, FileEnumeratorTest) {
// Test an empty directory.
file_util::FileEnumerator f0(test_dir_, true,
file_util::FileEnumerator f0(test_dir_.ToWStringHack(), true,
file_util::FileEnumerator::FILES_AND_DIRECTORIES);
EXPECT_EQ(f0.Next(), L"");
EXPECT_EQ(f0.Next(), L"");
// create the directories
std::wstring dir1 = test_dir_;
file_util::AppendToPath(&dir1, L"dir1");
FilePath dir1 = test_dir_.Append(FILE_PATH_LITERAL("dir1"));
EXPECT_TRUE(file_util::CreateDirectory(dir1));
std::wstring dir2 = test_dir_;
file_util::AppendToPath(&dir2, L"dir2");
FilePath dir2 = test_dir_.Append(FILE_PATH_LITERAL("dir2"));
EXPECT_TRUE(file_util::CreateDirectory(dir2));
std::wstring dir2inner = dir2;
file_util::AppendToPath(&dir2inner, L"inner");
FilePath dir2inner = dir2.Append(FILE_PATH_LITERAL("inner"));
EXPECT_TRUE(file_util::CreateDirectory(dir2inner));
// create the files
std::wstring dir2file = dir2;
file_util::AppendToPath(&dir2file, L"dir2file.txt");
FilePath dir2file = dir2.Append(FILE_PATH_LITERAL("dir2file.txt"));
CreateTextFile(dir2file, L"");
std::wstring dir2innerfile = dir2inner;
file_util::AppendToPath(&dir2innerfile, L"innerfile.txt");
FilePath dir2innerfile = dir2inner.Append(FILE_PATH_LITERAL("innerfile.txt"));
CreateTextFile(dir2innerfile, L"");
std::wstring file1 = test_dir_;
file_util::AppendToPath(&file1, L"file1.txt");
FilePath file1 = test_dir_.Append(FILE_PATH_LITERAL("file1.txt"));
CreateTextFile(file1, L"");
std::wstring file2_rel = dir2;
file_util::AppendToPath(&file2_rel, L"..");
file_util::AppendToPath(&file2_rel, L"file2.txt");
FilePath file2_rel =
dir2.Append(FilePath::kParentDirectory)
.Append(FILE_PATH_LITERAL("file2.txt"));
CreateTextFile(file2_rel, L"");
std::wstring file2_abs = test_dir_;
file_util::AppendToPath(&file2_abs, L"file2.txt");
FilePath file2_abs = test_dir_.Append(FILE_PATH_LITERAL("file2.txt"));
// Only enumerate files.
file_util::FileEnumerator f1(test_dir_, true,
file_util::FileEnumerator f1(test_dir_.ToWStringHack(), true,
file_util::FileEnumerator::FILES);
FindResultCollector c1(f1);
EXPECT_TRUE(c1.HasFile(file1));
@ -877,7 +867,7 @@ TEST_F(FileUtilTest, FileEnumeratorTest) {
EXPECT_EQ(c1.size(), 4);
// Only enumerate directories.
file_util::FileEnumerator f2(test_dir_, true,
file_util::FileEnumerator f2(test_dir_.ToWStringHack(), true,
file_util::FileEnumerator::DIRECTORIES);
FindResultCollector c2(f2);
EXPECT_TRUE(c2.HasFile(dir1));
@ -887,14 +877,14 @@ TEST_F(FileUtilTest, FileEnumeratorTest) {
// Only enumerate directories non-recursively.
file_util::FileEnumerator f2_non_recursive(
test_dir_, false, file_util::FileEnumerator::DIRECTORIES);
test_dir_.ToWStringHack(), false, file_util::FileEnumerator::DIRECTORIES);
FindResultCollector c2_non_recursive(f2_non_recursive);
EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
EXPECT_EQ(c2_non_recursive.size(), 2);
// Enumerate files and directories.
file_util::FileEnumerator f3(test_dir_, true,
file_util::FileEnumerator f3(test_dir_.ToWStringHack(), true,
file_util::FileEnumerator::FILES_AND_DIRECTORIES);
FindResultCollector c3(f3);
EXPECT_TRUE(c3.HasFile(dir1));
@ -907,7 +897,7 @@ TEST_F(FileUtilTest, FileEnumeratorTest) {
EXPECT_EQ(c3.size(), 7);
// Non-recursive operation.
file_util::FileEnumerator f4(test_dir_, false,
file_util::FileEnumerator f4(test_dir_.ToWStringHack(), false,
file_util::FileEnumerator::FILES_AND_DIRECTORIES);
FindResultCollector c4(f4);
EXPECT_TRUE(c4.HasFile(dir2));
@ -917,7 +907,7 @@ TEST_F(FileUtilTest, FileEnumeratorTest) {
EXPECT_EQ(c4.size(), 4);
// Enumerate with a pattern.
file_util::FileEnumerator f5(test_dir_, true,
file_util::FileEnumerator f5(test_dir_.ToWStringHack(), true,
file_util::FileEnumerator::FILES_AND_DIRECTORIES, L"dir*");
FindResultCollector c5(f5);
EXPECT_TRUE(c5.HasFile(dir1));
@ -929,7 +919,7 @@ TEST_F(FileUtilTest, FileEnumeratorTest) {
// Make sure the destructor closes the find handle while in the middle of a
// query to allow TearDown to delete the directory.
file_util::FileEnumerator f6(test_dir_, true,
file_util::FileEnumerator f6(test_dir_.ToWStringHack(), true,
file_util::FileEnumerator::FILES_AND_DIRECTORIES);
EXPECT_FALSE(f6.Next().empty()); // Should have found something
// (we don't care what).

@ -10,6 +10,7 @@
#include <time.h>
#include <string>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/scoped_handle.h"
#include "base/string_util.h"
@ -32,11 +33,11 @@ std::wstring GetDirectoryFromPath(const std::wstring& path) {
return directory;
}
bool AbsolutePath(std::wstring* path) {
bool AbsolutePath(FilePath* path) {
wchar_t file_path_buf[MAX_PATH];
if (!_wfullpath(file_path_buf, path->c_str(), MAX_PATH))
if (!_wfullpath(file_path_buf, path->value().c_str(), MAX_PATH))
return false;
*path = file_path_buf;
*path = FilePath(file_path_buf);
return true;
}
@ -66,14 +67,14 @@ int CountFilesCreatedAfter(const std::wstring& path,
return file_count;
}
bool Delete(const std::wstring& path, bool recursive) {
if (path.length() >= MAX_PATH)
bool Delete(const FilePath& path, bool recursive) {
if (path.value().length() >= MAX_PATH)
return false;
// If we're not recursing use DeleteFile; it should be faster. DeleteFile
// fails if passed a directory though, which is why we fall through on
// failure to the SHFileOperation.
if (!recursive && DeleteFile(path.c_str()) != 0)
if (!recursive && DeleteFile(path.value().c_str()) != 0)
return true;
// SHFILEOPSTRUCT wants the path to be terminated with two NULLs,
@ -81,7 +82,7 @@ bool Delete(const std::wstring& path, bool recursive) {
// into the rest of the buffer.
wchar_t double_terminated_path[MAX_PATH + 1] = {0};
#pragma warning(suppress:4996) // don't complain about wcscpy deprecation
wcscpy(double_terminated_path, path.c_str());
wcscpy(double_terminated_path, path.value().c_str());
SHFILEOPSTRUCT file_operation = {0};
file_operation.wFunc = FO_DELETE;
@ -92,29 +93,36 @@ bool Delete(const std::wstring& path, bool recursive) {
return (SHFileOperation(&file_operation) == 0);
}
bool Move(const std::wstring& from_path, const std::wstring& to_path) {
bool Move(const FilePath& from_path, const FilePath& to_path) {
// NOTE: I suspect we could support longer paths, but that would involve
// analyzing all our usage of files.
if (from_path.length() >= MAX_PATH || to_path.length() >= MAX_PATH)
if (from_path.value().length() >= MAX_PATH ||
to_path.value().length() >= MAX_PATH) {
return false;
return (MoveFileEx(from_path.c_str(), to_path.c_str(),
}
return (MoveFileEx(from_path.value().c_str(), to_path.value().c_str(),
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) != 0);
}
bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
// NOTE: I suspect we could support longer paths, but that would involve
// analyzing all our usage of files.
if (from_path.length() >= MAX_PATH || to_path.length() >= MAX_PATH)
if (from_path.value().length() >= MAX_PATH ||
to_path.value().length() >= MAX_PATH) {
return false;
return (::CopyFile(from_path.c_str(), to_path.c_str(), false) != 0);
}
return (::CopyFile(from_path.value().c_str(), to_path.value().c_str(),
false) != 0);
}
bool ShellCopy(const std::wstring& from_path, const std::wstring& to_path,
bool ShellCopy(const FilePath& from_path, const FilePath& to_path,
bool recursive) {
// NOTE: I suspect we could support longer paths, but that would involve
// analyzing all our usage of files.
if (from_path.length() >= MAX_PATH || to_path.length() >= MAX_PATH)
if (from_path.value().length() >= MAX_PATH ||
to_path.value().length() >= MAX_PATH) {
return false;
}
// SHFILEOPSTRUCT wants the path to be terminated with two NULLs,
// so we have to use wcscpy because wcscpy_s writes non-NULLs
@ -122,9 +130,9 @@ bool ShellCopy(const std::wstring& from_path, const std::wstring& to_path,
wchar_t double_terminated_path_from[MAX_PATH + 1] = {0};
wchar_t double_terminated_path_to[MAX_PATH + 1] = {0};
#pragma warning(suppress:4996) // don't complain about wcscpy deprecation
wcscpy(double_terminated_path_from, from_path.c_str());
wcscpy(double_terminated_path_from, from_path.value().c_str());
#pragma warning(suppress:4996) // don't complain about wcscpy deprecation
wcscpy(double_terminated_path_to, to_path.c_str());
wcscpy(double_terminated_path_to, to_path.value().c_str());
SHFILEOPSTRUCT file_operation = {0};
file_operation.wFunc = FO_COPY;
@ -138,7 +146,7 @@ bool ShellCopy(const std::wstring& from_path, const std::wstring& to_path,
return (SHFileOperation(&file_operation) == 0);
}
bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
bool CopyDirectory(const FilePath& from_path, const FilePath& to_path,
bool recursive) {
if (recursive)
return ShellCopy(from_path, to_path, true);
@ -154,13 +162,12 @@ bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
ShellCopy(from_path, to_path, false);
}
std::wstring directory(from_path);
AppendToPath(&directory, L"*.*");
FilePath directory = from_path.Append(L"*.*");
return ShellCopy(directory, to_path, false);
}
bool PathExists(const std::wstring& path) {
return (GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES);
bool PathExists(const FilePath& path) {
return (GetFileAttributes(path.value().c_str()) != INVALID_FILE_ATTRIBUTES);
}
bool PathIsWritable(const std::wstring& path) {
@ -176,8 +183,8 @@ bool PathIsWritable(const std::wstring& path) {
return true;
}
bool DirectoryExists(const std::wstring& path) {
DWORD fileattr = GetFileAttributes(path.c_str());
bool DirectoryExists(const FilePath& path) {
DWORD fileattr = GetFileAttributes(path.value().c_str());
if (fileattr != INVALID_FILE_ATTRIBUTES)
return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0;
return false;
@ -372,13 +379,17 @@ bool IsDirectoryEmpty(const std::wstring& dir_path) {
return false;
}
bool GetTempDir(std::wstring* path) {
bool GetTempDir(FilePath* path) {
wchar_t temp_path[MAX_PATH + 1];
DWORD path_len = ::GetTempPath(MAX_PATH, temp_path);
if (path_len >= MAX_PATH || path_len <= 0)
return false;
path->assign(temp_path);
TrimTrailingSeparator(path);
// TODO(evanm): the old behavior of this function was to always strip the
// trailing slash. We duplicate this here, but it shouldn't be necessary
// when everyone is using the appropriate FilePath APIs.
std::wstring path_str(temp_path);
TrimTrailingSeparator(&path_str);
*path = FilePath(path_str);
return true;
}
@ -438,10 +449,10 @@ bool CreateNewTempDirectory(const std::wstring& prefix,
return true;
}
bool CreateDirectory(const std::wstring& full_path) {
bool CreateDirectory(const FilePath& full_path) {
if (DirectoryExists(full_path))
return true;
int err = SHCreateDirectoryEx(NULL, full_path.c_str(), NULL);
int err = SHCreateDirectoryEx(NULL, full_path.value().c_str(), NULL);
return err == ERROR_SUCCESS;
}
@ -460,6 +471,15 @@ bool GetFileInfo(const std::wstring& file_path, FileInfo* results) {
return true;
}
FILE* OpenFile(const FilePath& filename, const char* mode) {
std::wstring w_mode = ASCIIToWide(std::string(mode));
FILE* file;
if (_wfopen_s(&file, filename.value().c_str(), w_mode.c_str()) != 0) {
return NULL;
}
return file;
}
FILE* OpenFile(const std::string& filename, const char* mode) {
FILE* file;
if (fopen_s(&file, filename.c_str(), mode) != 0) {
@ -469,12 +489,7 @@ FILE* OpenFile(const std::string& filename, const char* mode) {
}
FILE* OpenFile(const std::wstring& filename, const char* mode) {
std::wstring w_mode = ASCIIToWide(std::string(mode));
FILE* file;
if (_wfopen_s(&file, filename.c_str(), w_mode.c_str()) != 0) {
return NULL;
}
return file;
return OpenFile(FilePath(filename), mode);
}
int ReadFile(const std::wstring& filename, char* data, int size) {
@ -556,14 +571,18 @@ bool RenameFileAndResetSecurityDescriptor(
}
// Gets the current working directory for the process.
bool GetCurrentDirectory(std::wstring* dir) {
bool GetCurrentDirectory(FilePath* dir) {
wchar_t system_buffer[MAX_PATH];
system_buffer[0] = 0;
DWORD len = ::GetCurrentDirectory(MAX_PATH, system_buffer);
if (len == 0 || len > MAX_PATH)
return false;
*dir = system_buffer;
file_util::TrimTrailingSeparator(dir);
// TODO(evanm): the old behavior of this function was to always strip the
// trailing slash. We duplicate this here, but it shouldn't be necessary
// when everyone is using the appropriate FilePath APIs.
std::wstring dir_str(system_buffer);
file_util::TrimTrailingSeparator(&dir_str);
*dir = FilePath(dir_str);
return true;
}

@ -12,8 +12,9 @@
#include "base/icu_util.h"
#include "base/logging.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/sys_string_conversions.h"
#include "unicode/putil.h"
@ -76,10 +77,10 @@ bool Initialize() {
// For now, expect the data file to be alongside the executable.
// This is sufficient while we work on unit tests, but will eventually
// likely live in a data directory.
std::wstring data_path;
FilePath data_path;
bool path_ok = PathService::Get(base::DIR_EXE, &data_path);
DCHECK(path_ok);
u_setDataDirectory(base::SysWideToNativeMB(data_path).c_str());
u_setDataDirectory(data_path.value().c_str());
// Only look for the packaged data file;
// the default behavior is to look for individual files.
UErrorCode err = U_ZERO_ERROR;

@ -10,8 +10,9 @@
#include <shlobj.h>
#endif
#include "base/hash_tables.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/hash_tables.h"
#include "base/lock.h"
#include "base/logging.h"
#include "base/singleton.h"
@ -30,7 +31,7 @@ namespace base {
namespace {
typedef base::hash_map<int, std::wstring> PathMap;
typedef base::hash_map<int, FilePath> PathMap;
typedef base::hash_set<int> PathSet;
// We keep a linked list of providers. In a debug build we ensure that no two
@ -127,7 +128,7 @@ static PathData* GetPathData() {
// static
bool PathService::GetFromCache(int key, std::wstring* result) {
bool PathService::GetFromCache(int key, FilePath* result) {
PathData* path_data = GetPathData();
AutoLock scoped_lock(path_data->lock);
@ -141,7 +142,7 @@ bool PathService::GetFromCache(int key, std::wstring* result) {
}
// static
void PathService::AddToCache(int key, const std::wstring& path) {
void PathService::AddToCache(int key, const FilePath& path) {
PathData* path_data = GetPathData();
AutoLock scoped_lock(path_data->lock);
// Save the computed path in our cache.
@ -152,7 +153,7 @@ void PathService::AddToCache(int key, const std::wstring& path) {
// characters). This isn't supported very well by Windows right now, so it is
// moot, but we should keep this in mind for the future.
// static
bool PathService::Get(int key, std::wstring* result) {
bool PathService::Get(int key, FilePath* result) {
PathData* path_data = GetPathData();
DCHECK(path_data);
DCHECK(result);
@ -165,25 +166,36 @@ bool PathService::Get(int key, std::wstring* result) {
if (GetFromCache(key, result))
return true;
std::wstring path;
std::wstring path_string;
// search providers for the requested path
// NOTE: it should be safe to iterate here without the lock
// since RegisterProvider always prepends.
Provider* provider = path_data->providers;
while (provider) {
if (provider->func(key, &path))
if (provider->func(key, &path_string))
break;
DCHECK(path.empty()) << "provider should not have modified path";
DCHECK(path_string.empty()) << "provider should not have modified path";
provider = provider->next;
}
if (path.empty())
if (path_string.empty())
return false;
FilePath path = FilePath::FromWStringHack(path_string);
AddToCache(key, path);
result->swap(path);
*result = path;
return true;
}
// static
bool PathService::Get(int key, std::wstring* result) {
// Deprecated compatibility function.
FilePath path;
if (!Get(key, &path))
return false;
*result = path.ToWStringHack();
return true;
}
@ -211,7 +223,7 @@ bool PathService::Override(int key, const std::wstring& path) {
file_util::TrimTrailingSeparator(&file_path);
AutoLock scoped_lock(path_data->lock);
path_data->cache[key] = file_path;
path_data->cache[key] = FilePath::FromWStringHack(file_path);
path_data->overrides.insert(key);
return true;
}

@ -19,6 +19,8 @@
#include "base/base_paths.h"
class FilePath;
// The path service is a global table mapping keys to file system paths. It is
// OK to use this service from multiple threads.
//
@ -31,6 +33,9 @@ class PathService {
//
// Returns true if the directory or file was successfully retrieved. On
// failure, 'path' will not be changed.
static bool Get(int key, FilePath* path);
// This version, producing a wstring, is deprecated and only kept around
// until we can fix all callers.
static bool Get(int key, std::wstring* path);
// Overrides the path to a special directory or file. This cannot be used to
@ -66,8 +71,8 @@ class PathService {
int key_start,
int key_end);
private:
static bool GetFromCache(int key, std::wstring* path);
static void AddToCache(int key, const std::wstring& path);
static bool GetFromCache(int key, FilePath* path);
static void AddToCache(int key, const FilePath& path);
};

@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/path_service.h"
#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/platform_test.h"
#if defined(OS_WIN)
#include "base/win_util.h"
@ -18,9 +20,9 @@ namespace {
// Returns true if PathService::Get returns true and sets the path parameter
// to non-empty for the given PathService::DirType enumeration value.
bool ReturnsValidPath(int dir_type) {
std::wstring path;
FilePath path;
bool result = PathService::Get(dir_type, &path);
return result && !path.empty() && file_util::PathExists(path);
return result && !path.value().empty() && file_util::PathExists(path);
}
#if defined(OS_WIN)

@ -4,6 +4,7 @@
#include "base/trace_event.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
@ -21,7 +22,8 @@ static const char* kEventTypeNames[] = {
"INSTANT"
};
static const wchar_t* kLogFileName = L"trace_%d.log";
static const FilePath::CharType* kLogFileName =
FILE_PATH_LITERAL("trace_%d.log");
TraceLog::TraceLog() : enabled_(false), log_file_(NULL) {
ProcessHandle proc = process_util::GetCurrentProcessHandle();
@ -83,15 +85,16 @@ void TraceLog::CloseLogFile() {
}
bool TraceLog::OpenLogFile() {
std::wstring pid_filename =
StringPrintf(kLogFileName, process_util::GetCurrentProcId());
std::wstring log_file_name;
PathService::Get(base::DIR_EXE, &log_file_name);
file_util::AppendToPath(&log_file_name, pid_filename);
log_file_ = file_util::OpenFile(log_file_name, "a");
FilePath::StringType pid_filename =
StringPrintf(kLogFileName, process_util::GetCurrentProcId());
FilePath log_file_path;
if (!PathService::Get(base::DIR_EXE, &log_file_path))
return false;
log_file_path = log_file_path.Append(pid_filename);
log_file_ = file_util::OpenFile(log_file_path, "a");
if (!log_file_) {
// try the current directory
log_file_ = file_util::OpenFile(pid_filename, "a");
log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
if (!log_file_) {
return false;
}

@ -73,7 +73,7 @@ class DownloadTest : public UITest {
// Find the path on the client.
std::wstring file_on_client(download_prefix_);
file_on_client.append(client_filename);
EXPECT_PRED1(file_util::PathExists, file_on_client);
EXPECT_TRUE(file_util::PathExists(file_on_client));
// Find the path on the server.
std::wstring file_on_server;
@ -84,14 +84,15 @@ class DownloadTest : public UITest {
ASSERT_TRUE(file_util::PathExists(file_on_server));
// Check that we downloaded the file correctly.
EXPECT_PRED2(file_util::ContentsEqual, file_on_server, file_on_client);
EXPECT_TRUE(file_util::ContentsEqual(file_on_server,
file_on_client));
// Check if the Zone Identifier is correclty set.
if (VolumeSupportsADS(file_on_client))
CheckZoneIdentifier(file_on_client);
// Delete the client copy of the file.
EXPECT_PRED2(file_util::Delete, file_on_client, false);
EXPECT_TRUE(file_util::Delete(file_on_client, false));
}
void CleanUpDownload(const std::wstring& file) {
@ -131,7 +132,7 @@ class DownloadTest : public UITest {
}
std::wstring filename = file_util::GetFilenameFromPath(url);
EXPECT_PRED1(file_util::PathExists, download_prefix_ + filename);
EXPECT_TRUE(file_util::PathExists(download_prefix_ + filename));
// Delete the file we just downloaded.
for (int i = 0; i < 10; ++i) {

@ -43,7 +43,7 @@ class SavePageTest : public UITest {
EXPECT_TRUE(file_util::GetFileSize(client_file, &client_file_size));
EXPECT_TRUE(file_util::GetFileSize(server_file_name, &server_file_size));
EXPECT_EQ(client_file_size, server_file_size);
EXPECT_PRED2(file_util::ContentsEqual, client_file, server_file_name);
EXPECT_TRUE(file_util::ContentsEqual(client_file, server_file_name));
}
EXPECT_TRUE(DieFileDie(client_file, false));