Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
| 6 | 6 |
| 7 #include <errno.h> | |
| 7 #include <fcntl.h> | 8 #include <fcntl.h> |
| 8 #include <fnmatch.h> | 9 #include <fnmatch.h> |
| 9 #include <fts.h> | 10 #include <fts.h> |
| 10 #include <libgen.h> | 11 #include <libgen.h> |
| 12 #include <string.h> | |
| 11 #include <sys/errno.h> | 13 #include <sys/errno.h> |
| 12 #include <sys/stat.h> | 14 #include <sys/stat.h> |
| 13 #include <time.h> | 15 #include <time.h> |
| 14 | 16 |
| 15 #include <fstream> | 17 #include <fstream> |
| 16 | 18 |
| 17 #include "base/basictypes.h" | 19 #include "base/basictypes.h" |
| 18 #include "base/logging.h" | 20 #include "base/logging.h" |
| 19 #include "base/string_util.h" | 21 #include "base/string_util.h" |
| 20 | 22 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 return ret; | 59 return ret; |
| 58 } | 60 } |
| 59 if (!S_ISDIR(file_info.st_mode)) | 61 if (!S_ISDIR(file_info.st_mode)) |
| 60 return (unlink(utf8_path) == 0); | 62 return (unlink(utf8_path) == 0); |
| 61 if (!recursive) | 63 if (!recursive) |
| 62 return (rmdir(utf8_path) == 0); | 64 return (rmdir(utf8_path) == 0); |
| 63 | 65 |
| 64 bool success = true; | 66 bool success = true; |
| 65 int ftsflags = FTS_PHYSICAL | FTS_NOSTAT; | 67 int ftsflags = FTS_PHYSICAL | FTS_NOSTAT; |
| 66 char top_dir[PATH_MAX]; | 68 char top_dir[PATH_MAX]; |
| 67 base::strlcpy(top_dir, utf8_path, sizeof(top_dir)); | 69 if (base::strlcpy(top_dir, utf8_path, |
| 70 arraysize(top_dir)) >= arraysize(top_dir)) { | |
| 71 return false; | |
| 72 } | |
| 68 char* dir_list[2] = { top_dir, NULL }; | 73 char* dir_list[2] = { top_dir, NULL }; |
| 69 FTS* fts = fts_open(dir_list, ftsflags, NULL); | 74 FTS* fts = fts_open(dir_list, ftsflags, NULL); |
| 70 if (fts) { | 75 if (fts) { |
| 71 FTSENT* fts_ent = fts_read(fts); | 76 FTSENT* fts_ent = fts_read(fts); |
| 72 while (success && fts_ent != NULL) { | 77 while (success && fts_ent != NULL) { |
| 73 switch (fts_ent->fts_info) { | 78 switch (fts_ent->fts_info) { |
| 74 case FTS_DNR: | 79 case FTS_DNR: |
| 75 case FTS_ERR: | 80 case FTS_ERR: |
| 76 // log error | 81 // log error |
| 77 success = false; | 82 success = false; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 97 fts_close(fts); | 102 fts_close(fts); |
| 98 } | 103 } |
| 99 return success; | 104 return success; |
| 100 } | 105 } |
| 101 | 106 |
| 102 bool Move(const std::wstring& from_path, const std::wstring& to_path) { | 107 bool Move(const std::wstring& from_path, const std::wstring& to_path) { |
| 103 return (rename(WideToUTF8(from_path).c_str(), | 108 return (rename(WideToUTF8(from_path).c_str(), |
| 104 WideToUTF8(to_path).c_str()) == 0); | 109 WideToUTF8(to_path).c_str()) == 0); |
| 105 } | 110 } |
| 106 | 111 |
| 107 bool CopyTree(const std::wstring& from_path, const std::wstring& to_path) { | 112 bool CopyDirectory(const std::wstring& from_path_wide, |
| 108 // TODO(erikkay): implement | 113 const std::wstring& to_path_wide, |
| 109 return false; | 114 bool recursive) { |
| 115 const std::string to_path = WideToUTF8(to_path_wide); | |
| 116 const std::string from_path = WideToUTF8(from_path_wide); | |
| 117 | |
| 118 // Some old callers of CopyDirectory want it to support wildcards. | |
| 119 // After some discussion, we decided to fix those callers. | |
| 120 // Break loudly here if anyone tries to do this. | |
| 121 // TODO(evanm): remove this once we're sure it's ok. | |
|
Erik does not do reviews
2008/09/18 19:25:19
I'm not sure why we'd remove this. I think the TO
| |
| 122 DCHECK(to_path.find('*') == std::string::npos); | |
| 123 DCHECK(from_path.find('*') == std::string::npos); | |
| 124 | |
| 125 char top_dir[PATH_MAX]; | |
| 126 if (base::strlcpy(top_dir, from_path.c_str(), | |
| 127 arraysize(top_dir)) >= arraysize(top_dir)) { | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 131 char* dir_list[] = { top_dir, NULL }; | |
| 132 FTS* fts = fts_open(dir_list, FTS_PHYSICAL | FTS_NOSTAT, NULL); | |
| 133 if (!fts) { | |
| 134 LOG(ERROR) << "fts_open failed: " << strerror(errno); | |
| 135 return false; | |
| 136 } | |
| 137 | |
| 138 int error = 0; | |
| 139 FTSENT* ent; | |
| 140 while (!error && (ent = fts_read(fts)) != NULL) { | |
| 141 // ent->fts_path is the source path, including from_path, so paste | |
| 142 // the suffix after from_path onto to_path to create the target_path. | |
| 143 const std::string target_path = to_path + &ent->fts_path[from_path.size()]; | |
| 144 switch (ent->fts_info) { | |
| 145 case FTS_D: // Preorder directory. | |
| 146 // If we encounter a subdirectory in a non-recursive copy, prune it | |
| 147 // from the traversal. | |
| 148 if (!recursive && ent->fts_level > 0) { | |
| 149 if (fts_set(fts, ent, FTS_SKIP) != 0) | |
| 150 error = errno; | |
| 151 continue; | |
| 152 } | |
| 153 | |
| 154 // Try creating the target dir, continuing on it if it exists already. | |
| 155 if (mkdir(target_path.c_str(), 0777) != 0) { | |
| 156 if (errno != EEXIST) | |
| 157 error = errno; | |
| 158 } | |
| 159 break; | |
| 160 case FTS_F: // Regular file. | |
| 161 case FTS_NSOK: // File, no stat info requested. | |
| 162 // TODO(port): use a native file path rather than all these | |
| 163 // conversions. | |
| 164 errno = 0; | |
| 165 if (!CopyFile(UTF8ToWide(ent->fts_path), UTF8ToWide(target_path))) | |
| 166 error = errno ? errno : EINVAL; | |
| 167 break; | |
| 168 case FTS_DP: // Postorder directory. | |
| 169 case FTS_DOT: // "." or ".." | |
| 170 // Skip it. | |
| 171 continue; | |
| 172 case FTS_DC: // Directory causing a cycle. | |
| 173 // Skip this branch. | |
| 174 if (fts_set(fts, ent, FTS_SKIP) != 0) | |
| 175 error = errno; | |
| 176 break; | |
| 177 case FTS_DNR: // Directory cannot be read. | |
| 178 case FTS_ERR: // Error. | |
| 179 case FTS_NS: // Stat failed. | |
| 180 // Abort with the error. | |
| 181 error = ent->fts_errno; | |
| 182 break; | |
| 183 case FTS_SL: // Symlink. | |
| 184 case FTS_SLNONE: // Symlink with broken target. | |
| 185 LOG(WARNING) << "CopyDirectory() skipping symbolic link."; | |
| 186 continue; | |
| 187 case FTS_DEFAULT: // Some other sort of file. | |
| 188 LOG(WARNING) << "CopyDirectory() skipping weird file."; | |
| 189 continue; | |
| 190 default: | |
| 191 NOTREACHED(); | |
| 192 continue; // Hope for the best! | |
| 193 } | |
| 194 } | |
| 195 // fts_read may have returned NULL and set errno to indicate an error. | |
| 196 if (!error && errno != 0) | |
| 197 error = errno; | |
| 198 | |
| 199 if (!fts_close(fts)) { | |
| 200 // If we already have an error, let's use that error instead of the error | |
| 201 // fts_close set. | |
| 202 if (!error) | |
| 203 error = errno; | |
| 204 } | |
| 205 | |
| 206 if (error) { | |
| 207 LOG(ERROR) << "CopyDirectory(): " << strerror(error); | |
| 208 return false; | |
| 209 } | |
| 210 return true; | |
| 110 } | 211 } |
| 111 | 212 |
| 112 bool PathExists(const std::wstring& path) { | 213 bool PathExists(const std::wstring& path) { |
| 113 struct stat64 file_info; | 214 struct stat64 file_info; |
| 114 return (stat64(WideToUTF8(path).c_str(), &file_info) == 0); | 215 return (stat64(WideToUTF8(path).c_str(), &file_info) == 0); |
| 115 } | 216 } |
| 116 | 217 |
| 117 bool DirectoryExists(const std::wstring& path) { | 218 bool DirectoryExists(const std::wstring& path) { |
| 118 struct stat64 file_info; | 219 struct stat64 file_info; |
| 119 if (stat64(WideToUTF8(path).c_str(), &file_info) == 0) | 220 if (stat64(WideToUTF8(path).c_str(), &file_info) == 0) |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); | 440 return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next(); |
| 340 } else if (fts_ent->fts_info == FTS_F) { | 441 } else if (fts_ent->fts_info == FTS_F) { |
| 341 return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); | 442 return (file_type_ & FileEnumerator::FILES) ? cur_file : Next(); |
| 342 } | 443 } |
| 343 // TODO(erikkay) - verify that the other fts_info types aren't interesting | 444 // TODO(erikkay) - verify that the other fts_info types aren't interesting |
| 344 return Next(); | 445 return Next(); |
| 345 } | 446 } |
| 346 | 447 |
| 347 | 448 |
| 348 } // namespace file_util | 449 } // namespace file_util |
| OLD | NEW |