Port directory lister so test shell can view file directories.
Review URL: http://codereview.chromium.org/11437 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5725 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -14,6 +14,7 @@
|
||||
#include <windows.h>
|
||||
#elif defined(OS_POSIX)
|
||||
#include <fts.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@ -323,6 +324,15 @@ bool SetCurrentDirectory(const std::wstring& current_directory);
|
||||
// program where latency does not matter. This class is blocking.
|
||||
class FileEnumerator {
|
||||
public:
|
||||
#if defined(OS_WIN)
|
||||
typedef WIN32_FIND_DATA FindInfo;
|
||||
#elif defined(OS_POSIX)
|
||||
typedef struct {
|
||||
struct stat stat;
|
||||
std::string filename;
|
||||
} FindInfo;
|
||||
#endif
|
||||
|
||||
enum FILE_TYPE {
|
||||
FILES = 0x1,
|
||||
DIRECTORIES = 0x2,
|
||||
@ -361,6 +371,9 @@ class FileEnumerator {
|
||||
// Returns an empty string if there are no more results.
|
||||
std::wstring Next();
|
||||
|
||||
// Write the file info into |info|.
|
||||
void GetFindInfo(FindInfo* info);
|
||||
|
||||
private:
|
||||
std::wstring root_path_;
|
||||
bool recursive_;
|
||||
@ -380,6 +393,7 @@ class FileEnumerator {
|
||||
HANDLE find_handle_;
|
||||
#elif defined(OS_POSIX)
|
||||
FTS* fts_;
|
||||
FTSENT* fts_ent_;
|
||||
#endif
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator);
|
||||
|
@ -409,6 +409,16 @@ FileEnumerator::~FileEnumerator() {
|
||||
fts_close(fts_);
|
||||
}
|
||||
|
||||
void FileEnumerator::GetFindInfo(FindInfo* info) {
|
||||
DCHECK(info);
|
||||
|
||||
if (!is_in_find_op_)
|
||||
return;
|
||||
|
||||
memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat));
|
||||
info->filename.assign(fts_ent_->fts_name);
|
||||
}
|
||||
|
||||
// As it stands, this method calls itself recursively when the next item of
|
||||
// the fts enumeration doesn't match (type, pattern, etc.). In the case of
|
||||
// large directories with many files this can be quite deep.
|
||||
@ -417,12 +427,12 @@ std::wstring FileEnumerator::Next() {
|
||||
if (!is_in_find_op_) {
|
||||
if (pending_paths_.empty())
|
||||
return std::wstring();
|
||||
|
||||
|
||||
// The last find FindFirstFile operation is done, prepare a new one.
|
||||
root_path_ = pending_paths_.top();
|
||||
TrimTrailingSeparator(&root_path_);
|
||||
pending_paths_.pop();
|
||||
|
||||
|
||||
// Start a new find operation.
|
||||
int ftsflags = FTS_LOGICAL;
|
||||
char top_dir[PATH_MAX];
|
||||
@ -433,41 +443,41 @@ std::wstring FileEnumerator::Next() {
|
||||
return Next();
|
||||
is_in_find_op_ = true;
|
||||
}
|
||||
|
||||
FTSENT* fts_ent = fts_read(fts_);
|
||||
if (fts_ent == NULL) {
|
||||
|
||||
fts_ent_ = fts_read(fts_);
|
||||
if (fts_ent_ == NULL) {
|
||||
fts_close(fts_);
|
||||
fts_ = NULL;
|
||||
is_in_find_op_ = false;
|
||||
return Next();
|
||||
}
|
||||
|
||||
|
||||
// Level 0 is the top, which is always skipped.
|
||||
if (fts_ent->fts_level == 0)
|
||||
if (fts_ent_->fts_level == 0)
|
||||
return Next();
|
||||
|
||||
|
||||
// Patterns are only matched on the items in the top-most directory.
|
||||
// (see Windows implementation)
|
||||
if (fts_ent->fts_level == 1 && pattern_.length() > 0) {
|
||||
if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent->fts_path, 0) != 0) {
|
||||
if (fts_ent->fts_info == FTS_D)
|
||||
fts_set(fts_, fts_ent, FTS_SKIP);
|
||||
if (fts_ent_->fts_level == 1 && pattern_.length() > 0) {
|
||||
if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent_->fts_path, 0) != 0) {
|
||||
if (fts_ent_->fts_info == FTS_D)
|
||||
fts_set(fts_, fts_ent_, FTS_SKIP);
|
||||
return Next();
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring cur_file(UTF8ToWide(fts_ent->fts_path));
|
||||
if (fts_ent->fts_info == FTS_D) {
|
||||
|
||||
std::wstring cur_file(UTF8ToWide(fts_ent_->fts_path));
|
||||
if (fts_ent_->fts_info == FTS_D) {
|
||||
// If not recursive, then prune children.
|
||||
if (!recursive_)
|
||||
fts_set(fts_, fts_ent, FTS_SKIP);
|
||||
fts_set(fts_, fts_ent_, FTS_SKIP);
|
||||
return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next();
|
||||
} else if (fts_ent->fts_info == FTS_F) {
|
||||
} else if (fts_ent_->fts_info == FTS_F) {
|
||||
return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
|
||||
}
|
||||
// TODO(erikkay) - verify that the other fts_info types aren't interesting
|
||||
return Next();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace file_util
|
||||
|
@ -625,6 +625,15 @@ FileEnumerator::~FileEnumerator() {
|
||||
FindClose(find_handle_);
|
||||
}
|
||||
|
||||
void FileEnumerator::GetFindInfo(FindInfo* info) {
|
||||
DCHECK(info);
|
||||
|
||||
if (!is_in_find_op)
|
||||
return;
|
||||
|
||||
memcpy(info, &find_data_, sizeof(*info));
|
||||
}
|
||||
|
||||
std::wstring FileEnumerator::Next() {
|
||||
if (!is_in_find_op_) {
|
||||
if (pending_paths_.empty())
|
||||
|
Reference in New Issue
Block a user