diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-06 21:23:07 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-06 21:23:07 +0000 |
commit | 49930c3ae4d0bb40b94cfde0425e8c825a526144 (patch) | |
tree | 010ee4721b79bdfd7a22ef0ff7efe56630582b39 /base/test_file_util_posix.cc | |
parent | 6ae23b8bfb3ee39e3a158b4b83a2230dcfe06c45 (diff) | |
download | chromium_src-49930c3ae4d0bb40b94cfde0425e8c825a526144.zip chromium_src-49930c3ae4d0bb40b94cfde0425e8c825a526144.tar.gz chromium_src-49930c3ae4d0bb40b94cfde0425e8c825a526144.tar.bz2 |
Define _FILE_OFFSET_BITS=64 in order to support large files (>2GB).
_FILE_OFFSET_BITS=64 is incompatible with fts (issue 17492), so
file_util::Delete, file_util::CopyDirectory file_util::FileEnumerator are
reimplemented without fts. Delete and CopyDirectory are now implemented using
FileEnumerator.
Patch from vandebo@google.com, original review:
http://codereview.chromium.org/160479
BUG=13718,17492
TEST=none
Review URL: http://codereview.chromium.org/165085
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22670 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/test_file_util_posix.cc')
-rw-r--r-- | base/test_file_util_posix.cc | 126 |
1 files changed, 54 insertions, 72 deletions
diff --git a/base/test_file_util_posix.cc b/base/test_file_util_posix.cc index 66eb8a3..122dd04 100644 --- a/base/test_file_util_posix.cc +++ b/base/test_file_util_posix.cc @@ -5,7 +5,6 @@ #include "base/test_file_util.h" #include <errno.h> -#include <fts.h> #include <sys/types.h> #include <sys/stat.h> @@ -24,6 +23,7 @@ bool DieFileDie(const FilePath& file, bool recurse) { return file_util::Delete(file, recurse); } +// Mostly a verbatim copy of CopyDirectory bool CopyRecursiveDirNoCache(const std::wstring& source_dir, const std::wstring& dest_dir) { const FilePath from_path(FilePath::FromWStringHack(source_dir)); @@ -35,90 +35,72 @@ bool CopyRecursiveDirNoCache(const std::wstring& source_dir, return false; } - char* dir_list[] = { top_dir, NULL }; - FTS* fts = fts_open(dir_list, FTS_PHYSICAL | FTS_NOSTAT, NULL); - if (!fts) { - LOG(ERROR) << "fts_open failed: " << strerror(errno); + // This function does not properly handle destinations within the source + FilePath real_to_path = to_path; + if (PathExists(real_to_path)) { + if (!AbsolutePath(&real_to_path)) + return false; + } else { + real_to_path = real_to_path.DirName(); + if (!AbsolutePath(&real_to_path)) + return false; + } + if (real_to_path.value().compare(0, from_path.value().size(), + from_path.value()) == 0) return false; + + bool success = true; + FileEnumerator::FILE_TYPE traverse_type = + static_cast<FileEnumerator::FILE_TYPE>(FileEnumerator::FILES | + FileEnumerator::SHOW_SYM_LINKS | FileEnumerator::DIRECTORIES); + FileEnumerator traversal(from_path, true, traverse_type); + + // to_path may not exist yet, start the loop with to_path + FileEnumerator::FindInfo info; + FilePath current = from_path; + if (stat(from_path.value().c_str(), &info.stat) < 0) { + LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't stat source directory: " + << from_path.value() << " errno = " << errno; + success = false; } - int error = 0; - FTSENT* ent; - while (!error && (ent = fts_read(fts)) != NULL) { - // ent->fts_path is the source path, including from_path, so paste + while (success && !current.empty()) { + // current is the source path, including from_path, so paste // the suffix after from_path onto to_path to create the target_path. - std::string suffix(&ent->fts_path[from_path.value().size()]); + std::string suffix(¤t.value().c_str()[from_path.value().size()]); // Strip the leading '/' (if any). if (!suffix.empty()) { DCHECK_EQ('/', suffix[0]); suffix.erase(0, 1); } const FilePath target_path = to_path.Append(suffix); - switch (ent->fts_info) { - case FTS_D: // Preorder directory. - // Try creating the target dir, continuing on it if it exists already. - // Rely on the user's umask to produce correct permissions. - if (mkdir(target_path.value().c_str(), 0777) != 0) { - if (errno != EEXIST) - error = errno; - } - break; - case FTS_F: // Regular file. - case FTS_NSOK: // File, no stat info requested. - { - errno = 0; - FilePath source_path(ent->fts_path); - if (CopyFile(source_path, target_path)) { - bool success = EvictFileFromSystemCache(target_path); - DCHECK(success); - } else { - error = errno ? errno : EINVAL; - } - } - break; - case FTS_DP: // Postorder directory. - case FTS_DOT: // "." or ".." - // Skip it. - continue; - case FTS_DC: // Directory causing a cycle. - // Skip this branch. - if (fts_set(fts, ent, FTS_SKIP) != 0) - error = errno; - break; - case FTS_DNR: // Directory cannot be read. - case FTS_ERR: // Error. - case FTS_NS: // Stat failed. - // Abort with the error. - error = ent->fts_errno; - break; - case FTS_SL: // Symlink. - case FTS_SLNONE: // Symlink with broken target. - LOG(WARNING) << "skipping symbolic link: " << ent->fts_path; - continue; - case FTS_DEFAULT: // Some other sort of file. - LOG(WARNING) << "skipping file of unknown type: " << ent->fts_path; - continue; - default: - NOTREACHED(); - continue; // Hope for the best! + + if (S_ISDIR(info.stat.st_mode)) { + if (mkdir(target_path.value().c_str(), info.stat.st_mode & 01777) != 0 && + errno != EEXIST) { + LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't create directory: " << + target_path.value() << " errno = " << errno; + success = false; + } + } else if (S_ISREG(info.stat.st_mode)) { + if (CopyFile(current, target_path)) { + success = EvictFileFromSystemCache(target_path); + DCHECK(success); + } else { + LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't create file: " << + target_path.value(); + success = false; + } + } else { + LOG(WARNING) << "CopyRecursiveDirNoCache() skipping non-regular file: " << + current.value(); } - } - // fts_read may have returned NULL and set errno to indicate an error. - if (!error && errno != 0) - error = errno; - - if (!fts_close(fts)) { - // If we already have an error, let's use that error instead of the error - // fts_close set. - if (!error) - error = errno; - } - if (error) { - LOG(ERROR) << strerror(error); - return false; + current = traversal.Next(); + traversal.GetFindInfo(&info); } - return true; + + return success; } } // namespace file_util |