1
0
forked from mirrors/0ad
Files
0ad/source/lib/file/vfs/vfs_lookup.cpp
T
janwas c4654fd8fa bits: avoid sign conversion warning
debug: cleanup
ogl_tex, tex: use full-width types to avoid truncation warnings
wdbg_sym.cpp: skip __suppress and __profile symbols; add additional hex
display for floats; cleanup
wdll_ver.cpp: cppdoc+cleanup (remove non-reentrant C interface, replace
with std::string)
sysdep: add cppdoc

everything else: flag parameters are now consistently size_t instead of
int (avoids warnings, allows slightly better code on x64)

This was SVN commit r6392.
2008-09-18 11:27:55 +00:00

85 lines
2.6 KiB
C++

/**
* =========================================================================
* File : vfs_lookup.cpp
* Project : 0 A.D.
* Description : look up directories/files by traversing path components.
* =========================================================================
*/
// license: GPL; see lib/license.txt
#include "precompiled.h"
#include "vfs_lookup.h"
#include "lib/path_util.h" // path_foreach_component
#include "vfs.h" // error codes
#include "vfs_tree.h"
#include "vfs_populate.h"
#include "lib/timer.h"
TIMER_ADD_CLIENT(tc_lookup);
LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDirectory*& directory, VfsFile** pfile, size_t flags)
{
TIMER_ACCRUE(tc_lookup);
// extract and validate flags (ensure no unknown bits are set)
const bool addMissingDirectories = (flags & VFS_LOOKUP_ADD) != 0;
const bool createMissingDirectories = (flags & VFS_LOOKUP_CREATE) != 0;
debug_assert((flags & ~(VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE)) == 0);
if(pfile)
*pfile = 0;
directory = startDirectory;
RETURN_ERR(vfs_Populate(directory));
// early-out for pathname == "" when mounting into VFS root
if(pathname.empty()) // (prevent iterator error in loop end condition)
return INFO::OK;
// for each directory component:
VfsPath::iterator it; // (used outside of loop to get filename)
for(it = pathname.begin(); it != --pathname.end(); ++it)
{
const std::string& subdirectoryName = *it;
VfsDirectory* subdirectory = directory->GetSubdirectory(subdirectoryName);
if(!subdirectory)
{
if(addMissingDirectories)
subdirectory = directory->AddSubdirectory(subdirectoryName);
else
return ERR::VFS_DIR_NOT_FOUND; // NOWARN
}
if(createMissingDirectories && !subdirectory->AssociatedDirectory())
{
Path currentPath;
if(directory->AssociatedDirectory()) // (is NULL when mounting into root)
currentPath = directory->AssociatedDirectory()->GetPath()/subdirectoryName;
if(mkdir(currentPath.external_directory_string().c_str(), S_IRWXO|S_IRWXU|S_IRWXG) == 0)
{
PRealDirectory realDirectory(new RealDirectory(currentPath, 0, 0));
RETURN_ERR(vfs_Attach(subdirectory, realDirectory));
}
}
RETURN_ERR(vfs_Populate(subdirectory));
directory = subdirectory;
}
if(pfile)
{
const std::string& filename = *it;
debug_assert(filename != "."); // asked for file but specified directory path
*pfile = directory->GetFile(filename);
if(!*pfile)
return ERR::VFS_FILE_NOT_FOUND; // NOWARN
}
return INFO::OK;
}