1
0
forked from 0ad/0ad

vfs: fix mounting archive contents - now relative to mount point as it should.

added flags to vfs_mount that enable looking for archives and mounting
subdirectories (previously always done, but slow)
main: uses above flags when mounting

This was SVN commit r1695.
This commit is contained in:
janwas 2005-01-10 18:44:41 +00:00
parent e632c0ff1d
commit fba99c3414
3 changed files with 73 additions and 38 deletions

View File

@ -430,7 +430,7 @@ struct TDir
TDir* find_subdir(const char* d_name);
void clearR();
void displayR(int indent_level = 0);
int addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs = 0);
int addR(const char* p_path, const TLoc* dir_loc, bool recursive, TLocs* archive_locs);
};
@ -583,6 +583,8 @@ enum TreeLookupFlags
//
// if <flags> & LF_CREATE_MISSING, all missing subdirectory components are
// added to the VFS.
// if <flags> & LF_START_DIR, traversal starts at *pdir
// (used when looking up paths relative to a mount point).
// if <exact_path> != 0, it receives a copy of <path> with
// the exact case of each component as returned by the OS
// (useful for calling external case-sensitive code).
@ -894,11 +896,13 @@ static int dirent_cb(const char* name, const struct stat* s, uintptr_t user)
}
// add the directory <p_path>, its files, and all subdirectories
// (recursively) to this TDir, marking location as <dir_loc>.
// if archive_locs != 0, all archives found in this directory
// (but not subdirs! see below) are opened and their TLoc stored there.
int TDir::addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs)
// add the contents of directory <p_path> to this TDir,
// marking the files' locations as <dir_loc>.
// if desired, we recursively add the contents of subdirectories as well.
// if <archive_locs> != 0, all archives found in this directory only
// (not its subdirs! see below) are opened in alphabetical order,
// their files added, and a TLoc appended to <*archive_locs>.
int TDir::addR(const char* p_path, const TLoc* dir_loc, bool recursive, TLocs* archive_locs)
{
// more than one real dir mounted into VFS dir
// (=> can't create files for writing here)
@ -911,11 +915,13 @@ int TDir::addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs)
res_watch_dir(p_path, &watch);
#endif
// add files and subdirs to vdir
// add files and subdirs to this dir;
// also adds the contents of archives if archive_locs != 0.
const DirentCBParams params(this, dir_loc, archive_locs);
file_enum(p_path, dirent_cb, (uintptr_t)&params);
// recurse over all subdirs
if(recursive)
for(TDirIt it = subdirs.begin(); it != subdirs.end(); ++it)
{
TDir* subdir = &it->second;
@ -930,7 +936,7 @@ int TDir::addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs)
char p_subdir_path[PATH_MAX];
CHECK_ERR(path_append(p_subdir_path, p_path, d_subdir_name));
subdir->addR(p_subdir_path, dir_loc, (TLocs*)0);
subdir->addR(p_subdir_path, dir_loc, true, (TLocs*)0);
// note: archive_locs = 0 means we won't search for archives
// in subdirectories (slow!). this is currently required by
// the dirent_cb implementation anyway; see above.
@ -940,9 +946,10 @@ int TDir::addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs)
}
static int tree_add_dir(TDir* dir, const char* p_path, const TLoc* dir_loc, TLocs* archive_locs)
static int tree_add_dir(TDir* dir, const char* p_path, const TLoc* dir_loc,
bool recursive, TLocs* archive_locs)
{
return dir->addR(p_path, dir_loc, archive_locs);
return dir->addR(p_path, dir_loc, recursive, archive_locs);
}
@ -969,9 +976,12 @@ struct Mount
// real directory being mounted
const std::string p_real_path;
// see enum VfsMountFlags
int flags;
uint pri;
// storage for all Locs ensuing from this mounting.
// storage for all TLocs ensuing from this mounting.
// it's safe to store pointers to them: the Mount and Locs containers
// are std::lists, and all pointers are reset after unmounting something.
TLoc dir_loc;
@ -983,12 +993,17 @@ struct Mount
// multiple archives per dir support is required for patches.
Mount(const char* _v_mount_point, const char* _p_real_path, uint _pri)
: v_mount_point(_v_mount_point), p_real_path(_p_real_path),
dir_loc(0, _v_mount_point, _p_real_path, _pri), archive_locs()
Mount(const char* v_mount_point_, const char* p_real_path_, int flags_, uint pri_)
: v_mount_point(v_mount_point_), p_real_path(p_real_path_),
dir_loc(0, v_mount_point_, p_real_path_, pri_), archive_locs()
{
pri = _pri;
flags = flags_;
pri = pri_;
}
// no copy ctor, since some members are const
private:
Mount& operator=(const Mount&);
};
typedef std::list<Mount> Mounts;
@ -1005,6 +1020,7 @@ TIMER(remount);
const char* v_mount_point = m.v_mount_point.c_str();
const char* p_real_path = m.p_real_path.c_str();
const int flags = m.flags;
const uint pri = m.pri;
TLoc* dir_loc = &m.dir_loc;
TLocs& archive_locs = m.archive_locs;
@ -1012,7 +1028,7 @@ TIMER(remount);
// callers have a tendency to forget required trailing '/';
// complain if it's not there, unless path = "" (root dir).
#ifndef NDEBUG
size_t len = strlen(v_mount_point);
const size_t len = strlen(v_mount_point);
if(len && v_mount_point[len-1] != '/')
debug_warn("remount: path doesn't end in '/'");
#endif
@ -1020,9 +1036,12 @@ TIMER(remount);
TDir* dir;
CHECK_ERR(tree_lookup_dir(v_mount_point, &dir, LF_CREATE_MISSING));
const bool recursive = !!(flags & VFS_MOUNT_RECURSIVE);
TLocs* parchive_locs = (flags & VFS_MOUNT_ARCHIVES)? &archive_locs : 0;
// add all loose files and subdirectories (recursive).
// also mounts all archives in p_real_path and adds to archive_locs.
return tree_add_dir(dir, p_real_path, dir_loc, &archive_locs);
return tree_add_dir(dir, p_real_path, dir_loc, recursive, parchive_locs);
}
@ -1082,8 +1101,10 @@ static bool is_subpath(const char* s1, const char* s2)
// <pri>(ority) is not lower.
// all archives in <p_real_path> are also mounted, in alphabetical order.
//
// flags determines extra actions to perform; see VfsMountFlags.
//
// p_real_path = "." or "./" isn't allowed - see implementation for rationale.
int vfs_mount(const char* v_mount_point, const char* p_real_path, const uint pri)
int vfs_mount(const char* v_mount_point, const char* p_real_path, int flags, uint pri)
{
// make sure it's not already mounted, i.e. in mounts.
// also prevents mounting a parent directory of a previously mounted
@ -1107,7 +1128,7 @@ int vfs_mount(const char* v_mount_point, const char* p_real_path, const uint pri
return -1;
}
mounts.push_back(Mount(v_mount_point, p_real_path, pri));
mounts.push_back(Mount(v_mount_point, p_real_path, flags, pri));
// actually mount the entry
Mount& m = mounts.back();

View File

@ -39,6 +39,18 @@
// in English: '/' as path separator; trailing '/' required for dir names;
// no leading '/', since "" is the root dir.
enum VfsMountFlags
{
// the directory being mounted (but not its subdirs! see impl) will be
// searched for archives, and their contents added.
// use only if necessary, since this is slow (we need to check if
// each file is an archive, which entails reading the header).
VFS_MOUNT_ARCHIVES = 1,
// when mounting a directory, all directories beneath it are
// added recursively as well.
VFS_MOUNT_RECURSIVE = 2
};
// mount <p_real_dir> into the VFS at <vfs_mount_point>,
// which is created if it does not yet exist.
@ -46,8 +58,10 @@
// <pri>(ority) is not lower.
// all archives in <p_real_dir> are also mounted, in alphabetical order.
//
// flags determines extra actions to perform; see VfsMountFlags.
//
// p_real_dir = "." or "./" isn't allowed - see implementation for rationale.
extern int vfs_mount(const char* v_mount_point, const char* p_real_dir, uint pri);
extern int vfs_mount(const char* v_mount_point, const char* p_real_dir, int flags = 0, uint pri = 0);
// rebuild the VFS, i.e. re-mount everything. open files are not affected.
// necessary after loose files or directories change, so that the VFS

View File

@ -740,9 +740,9 @@ TIMER(InitVfs)
// display_startup_error(L"error setting current directory.\n"\
// L"argv[0] is probably incorrect. please start the game via command-line.");
vfs_mount("", "mods/official", 0);
vfs_mount("screenshots/", "screenshots", 0);
vfs_mount("profiles/", "profiles", 0);
vfs_mount("", "mods/official", VFS_MOUNT_RECURSIVE|VFS_MOUNT_ARCHIVES);
vfs_mount("screenshots/", "screenshots");
vfs_mount("profiles/", "profiles");
// don't try vfs_display yet: SDL_Init hasn't yet redirected stdout
}