// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/test/test_file_util.h" #include #include #include #include #include #include "base/logging.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" namespace file_util { bool DieFileDie(const FilePath& file, bool recurse) { // There is no need to workaround Windows problems on POSIX. // Just pass-through. return file_util::Delete(file, recurse); } // Mostly a verbatim copy of CopyDirectory bool CopyRecursiveDirNoCache(const FilePath& source_dir, const FilePath& dest_dir) { char top_dir[PATH_MAX]; if (base::strlcpy(top_dir, source_dir.value().c_str(), arraysize(top_dir)) >= arraysize(top_dir)) { return false; } // This function does not properly handle destinations within the source FilePath real_to_path = dest_dir; 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, source_dir.value().size(), source_dir.value()) == 0) return false; bool success = true; FileEnumerator::FILE_TYPE traverse_type = static_cast(FileEnumerator::FILES | FileEnumerator::SHOW_SYM_LINKS | FileEnumerator::DIRECTORIES); FileEnumerator traversal(source_dir, true, traverse_type); // dest_dir may not exist yet, start the loop with dest_dir FileEnumerator::FindInfo info; FilePath current = source_dir; if (stat(source_dir.value().c_str(), &info.stat) < 0) { LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't stat source directory: " << source_dir.value() << " errno = " << errno; success = false; } while (success && !current.empty()) { // |current| is the source path, including source_dir, so paste // the suffix after source_dir onto dest_dir to create the target_path. std::string suffix(¤t.value().c_str()[source_dir.value().size()]); // Strip the leading '/' (if any). if (!suffix.empty()) { DCHECK_EQ('/', suffix[0]); suffix.erase(0, 1); } const FilePath target_path = dest_dir.Append(suffix); 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(); } current = traversal.Next(); traversal.GetFindInfo(&info); } return success; } #if !defined(OS_LINUX) && !defined(OS_MACOSX) bool EvictFileFromSystemCache(const FilePath& file) { // There doesn't seem to be a POSIX way to cool the disk cache. NOTIMPLEMENTED(); return false; } #endif std::wstring FilePathAsWString(const FilePath& path) { return UTF8ToWide(path.value()); } FilePath WStringAsFilePath(const std::wstring& path) { return FilePath(WideToUTF8(path)); } } // namespace file_util