Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: base/file_util_posix.cc

Issue 3077: posix copydirectory implementation (Closed)
Patch Set: rebased Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/file_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | base/file_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698