1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/test/test_file_util.h" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <sys/types.h> 10 #include <sys/stat.h> 11 12 #include <string> 13 14 #include "base/logging.h" 15 #include "base/file_path.h" 16 #include "base/file_util.h" 17 #include "base/string_util.h" 18 #include "base/utf_string_conversions.h" 19 20 namespace file_util { 21 22 bool DieFileDie(const FilePath& file, bool recurse) { 23 // There is no need to workaround Windows problems on POSIX. 24 // Just pass-through. 25 return file_util::Delete(file, recurse); 26 } 27 28 // Mostly a verbatim copy of CopyDirectory 29 bool CopyRecursiveDirNoCache(const FilePath& source_dir, 30 const FilePath& dest_dir) { 31 char top_dir[PATH_MAX]; 32 if (base::strlcpy(top_dir, source_dir.value().c_str(), 33 arraysize(top_dir)) >= arraysize(top_dir)) { 34 return false; 35 } 36 37 // This function does not properly handle destinations within the source 38 FilePath real_to_path = dest_dir; 39 if (PathExists(real_to_path)) { 40 if (!AbsolutePath(&real_to_path)) 41 return false; 42 } else { 43 real_to_path = real_to_path.DirName(); 44 if (!AbsolutePath(&real_to_path)) 45 return false; 46 } 47 if (real_to_path.value().compare(0, source_dir.value().size(), 48 source_dir.value()) == 0) 49 return false; 50 51 bool success = true; 52 FileEnumerator::FILE_TYPE traverse_type = 53 static_cast<FileEnumerator::FILE_TYPE>(FileEnumerator::FILES | 54 FileEnumerator::SHOW_SYM_LINKS | FileEnumerator::DIRECTORIES); 55 FileEnumerator traversal(source_dir, true, traverse_type); 56 57 // dest_dir may not exist yet, start the loop with dest_dir 58 FileEnumerator::FindInfo info; 59 FilePath current = source_dir; 60 if (stat(source_dir.value().c_str(), &info.stat) < 0) { 61 LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't stat source directory: " 62 << source_dir.value() << " errno = " << errno; 63 success = false; 64 } 65 66 while (success && !current.empty()) { 67 // |current| is the source path, including source_dir, so paste 68 // the suffix after source_dir onto dest_dir to create the target_path. 69 std::string suffix(¤t.value().c_str()[source_dir.value().size()]); 70 // Strip the leading '/' (if any). 71 if (!suffix.empty()) { 72 DCHECK_EQ('/', suffix[0]); 73 suffix.erase(0, 1); 74 } 75 const FilePath target_path = dest_dir.Append(suffix); 76 77 if (S_ISDIR(info.stat.st_mode)) { 78 if (mkdir(target_path.value().c_str(), info.stat.st_mode & 01777) != 0 && 79 errno != EEXIST) { 80 LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't create directory: " << 81 target_path.value() << " errno = " << errno; 82 success = false; 83 } 84 } else if (S_ISREG(info.stat.st_mode)) { 85 if (CopyFile(current, target_path)) { 86 success = EvictFileFromSystemCache(target_path); 87 DCHECK(success); 88 } else { 89 LOG(ERROR) << "CopyRecursiveDirNoCache() couldn't create file: " << 90 target_path.value(); 91 success = false; 92 } 93 } else { 94 LOG(WARNING) << "CopyRecursiveDirNoCache() skipping non-regular file: " << 95 current.value(); 96 } 97 98 current = traversal.Next(); 99 traversal.GetFindInfo(&info); 100 } 101 102 return success; 103 } 104 105 #if !defined(OS_LINUX) && !defined(OS_MACOSX) 106 bool EvictFileFromSystemCache(const FilePath& file) { 107 // There doesn't seem to be a POSIX way to cool the disk cache. 108 NOTIMPLEMENTED(); 109 return false; 110 } 111 #endif 112 113 std::wstring FilePathAsWString(const FilePath& path) { 114 return UTF8ToWide(path.value()); 115 } 116 FilePath WStringAsFilePath(const std::wstring& path) { 117 return FilePath(WideToUTF8(path)); 118 } 119 120 } // namespace file_util 121