2004-08-24 13:26:32 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
|
|
#include "VFSUtil.h"
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "lib/res/file/vfs.h"
|
2004-08-24 13:26:32 +02:00
|
|
|
|
|
|
|
#include "CLogger.h"
|
|
|
|
#define LOG_CATEGORY "vfs"
|
|
|
|
|
2005-05-18 07:32:09 +02:00
|
|
|
#include <deque>
|
|
|
|
|
2004-08-24 13:26:32 +02:00
|
|
|
using namespace VFSUtil;
|
|
|
|
|
|
|
|
// Because I'm lazy, and it saves a few lines of code in other places:
|
2005-03-29 22:50:04 +02:00
|
|
|
bool VFSUtil::FindFiles (const CStr& dirname, const char* filter, FileList& files)
|
2004-08-24 13:26:32 +02:00
|
|
|
{
|
|
|
|
files.clear();
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
Handle dir = vfs_dir_open(dirname);
|
2004-08-24 13:26:32 +02:00
|
|
|
if (dir <= 0)
|
|
|
|
{
|
|
|
|
LOG(ERROR, LOG_CATEGORY, "Error opening directory '%s' (%lld)", dirname.c_str(), dir);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int err;
|
2005-08-09 17:55:44 +02:00
|
|
|
DirEnt entry;
|
|
|
|
while ((err = vfs_dir_next_ent(dir, &entry, filter)) == 0)
|
2004-08-24 13:26:32 +02:00
|
|
|
{
|
|
|
|
files.push_back(dirname+"/"+entry.name);
|
|
|
|
}
|
2004-11-23 22:11:00 +01:00
|
|
|
|
2004-12-01 22:37:01 +01:00
|
|
|
if (err != ERR_DIR_END)
|
2004-08-24 13:26:32 +02:00
|
|
|
{
|
|
|
|
LOG(ERROR, LOG_CATEGORY, "Error reading files from directory '%s' (%d)", dirname.c_str(), err);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
vfs_dir_close(dir);
|
2004-08-24 13:26:32 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
|
2004-11-07 22:30:47 +01:00
|
|
|
}
|
2005-03-27 03:44:41 +02:00
|
|
|
|
|
|
|
|
2005-05-03 07:03:27 +02:00
|
|
|
// call <cb> for each entry matching <user_filter> (see vfs_next_dirent) in
|
2005-08-09 17:55:44 +02:00
|
|
|
// directory <path>; if <recursive>, entries in subdirectories are
|
2005-03-27 19:27:49 +02:00
|
|
|
// also returned.
|
2005-03-27 03:44:41 +02:00
|
|
|
//
|
2005-03-27 19:27:49 +02:00
|
|
|
// note: EnumDirEntsCB path and ent are only valid during the callback.
|
2005-08-09 17:55:44 +02:00
|
|
|
int VFSUtil::EnumDirEnts(const CStr start_path, int flags, const char* user_filter,
|
|
|
|
EnumDirEntsCB cb, void* context)
|
2005-03-27 03:44:41 +02:00
|
|
|
{
|
2005-08-09 17:55:44 +02:00
|
|
|
debug_assert((flags & ~(RECURSIVE)) == 0);
|
|
|
|
const bool recursive = (flags & RECURSIVE) != 0;
|
|
|
|
|
2005-03-27 03:44:41 +02:00
|
|
|
char filter_buf[VFS_MAX_PATH];
|
|
|
|
const char* filter = user_filter;
|
|
|
|
bool want_dir = true;
|
|
|
|
if(user_filter)
|
|
|
|
{
|
|
|
|
if(user_filter[0] != '/')
|
|
|
|
want_dir = false;
|
|
|
|
|
|
|
|
// we need subdirectories and the caller hasn't already requested them
|
|
|
|
if(recursive && !want_dir)
|
|
|
|
{
|
|
|
|
snprintf(filter_buf, sizeof(filter_buf), "/|%s", user_filter);
|
|
|
|
filter = filter_buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// note: FIFO queue instead of recursion is much more efficient
|
|
|
|
// (less stack usage; avoids seeks by reading all entries in a
|
|
|
|
// directory consecutively)
|
|
|
|
|
2005-05-18 07:32:09 +02:00
|
|
|
std::deque<CStr> dir_queue;
|
2005-03-27 03:44:41 +02:00
|
|
|
dir_queue.push_back(start_path);
|
|
|
|
|
|
|
|
// for each directory:
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// get current directory path from queue
|
|
|
|
// note: can't refer to the queue contents - those are invalidated
|
|
|
|
// as soon as a directory is pushed onto it.
|
|
|
|
char path[VFS_MAX_PATH];
|
2005-08-09 17:55:44 +02:00
|
|
|
vfs_path_append(path, dir_queue.front().c_str(), "");
|
2005-03-27 03:44:41 +02:00
|
|
|
// vfs_open_dir checks this, so ignore failure
|
|
|
|
const size_t path_len = strlen(path);
|
|
|
|
dir_queue.pop_front();
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
Handle hdir = vfs_dir_open(path);
|
2005-03-27 03:44:41 +02:00
|
|
|
if(hdir <= 0)
|
|
|
|
{
|
2005-10-19 08:29:55 +02:00
|
|
|
debug_warn("vfs_open_dir failed");
|
2005-03-27 03:44:41 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for each entry (file, subdir) in directory:
|
2005-08-09 17:55:44 +02:00
|
|
|
DirEnt ent;
|
|
|
|
while(vfs_dir_next_ent(hdir, &ent, filter) == 0)
|
2005-03-27 03:44:41 +02:00
|
|
|
{
|
2005-08-09 17:55:44 +02:00
|
|
|
// build complete path (DirEnt only stores entry name)
|
2005-03-27 03:44:41 +02:00
|
|
|
strcpy_s(path+path_len, VFS_MAX_PATH-path_len, ent.name);
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
if(DIRENT_IS_DIR(&ent))
|
2005-03-27 03:44:41 +02:00
|
|
|
{
|
|
|
|
if(recursive)
|
|
|
|
dir_queue.push_back(path);
|
|
|
|
|
|
|
|
if(want_dir)
|
|
|
|
cb(path, &ent, context);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cb(path, &ent, context);
|
|
|
|
}
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
vfs_dir_close(hdir);
|
2005-03-27 03:44:41 +02:00
|
|
|
}
|
|
|
|
while(!dir_queue.empty());
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|