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); TDir* find_subdir(const char* d_name);
void clearR(); void clearR();
void displayR(int indent_level = 0); 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 // if <flags> & LF_CREATE_MISSING, all missing subdirectory components are
// added to the VFS. // 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 // if <exact_path> != 0, it receives a copy of <path> with
// the exact case of each component as returned by the OS // the exact case of each component as returned by the OS
// (useful for calling external case-sensitive code). // (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 // add the contents of directory <p_path> to this TDir,
// (recursively) to this TDir, marking location as <dir_loc>. // marking the files' locations as <dir_loc>.
// if archive_locs != 0, all archives found in this directory // if desired, we recursively add the contents of subdirectories as well.
// (but not subdirs! see below) are opened and their TLoc stored there. // if <archive_locs> != 0, all archives found in this directory only
int TDir::addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs) // (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 // more than one real dir mounted into VFS dir
// (=> can't create files for writing here) // (=> can't create files for writing here)
@ -911,38 +915,41 @@ int TDir::addR(const char* p_path, const TLoc* dir_loc, TLocs* archive_locs)
res_watch_dir(p_path, &watch); res_watch_dir(p_path, &watch);
#endif #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); const DirentCBParams params(this, dir_loc, archive_locs);
file_enum(p_path, dirent_cb, (uintptr_t)&params); file_enum(p_path, dirent_cb, (uintptr_t)&params);
// recurse over all subdirs // recurse over all subdirs
for(TDirIt it = subdirs.begin(); it != subdirs.end(); ++it) if(recursive)
{ for(TDirIt it = subdirs.begin(); it != subdirs.end(); ++it)
TDir* subdir = &it->second; {
const char* d_subdir_name = (it->first).c_str(); TDir* subdir = &it->second;
const char* d_subdir_name = (it->first).c_str();
// don't clutter the tree with versioning system dirs. // don't clutter the tree with versioning system dirs.
// only applicable for normal dirs; the archive builder // only applicable for normal dirs; the archive builder
// takes care of removing these there. // takes care of removing these there.
if(!strcmp(d_subdir_name, "CVS") || !strcmp(d_subdir_name, ".svn")) if(!strcmp(d_subdir_name, "CVS") || !strcmp(d_subdir_name, ".svn"))
continue; continue;
char p_subdir_path[PATH_MAX]; char p_subdir_path[PATH_MAX];
CHECK_ERR(path_append(p_subdir_path, p_path, d_subdir_name)); 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 // note: archive_locs = 0 means we won't search for archives
// in subdirectories (slow!). this is currently required by // in subdirectories (slow!). this is currently required by
// the dirent_cb implementation anyway; see above. // the dirent_cb implementation anyway; see above.
} }
return 0; return 0;
} }
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 // real directory being mounted
const std::string p_real_path; const std::string p_real_path;
// see enum VfsMountFlags
int flags;
uint pri; 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 // it's safe to store pointers to them: the Mount and Locs containers
// are std::lists, and all pointers are reset after unmounting something. // are std::lists, and all pointers are reset after unmounting something.
TLoc dir_loc; TLoc dir_loc;
@ -983,12 +993,17 @@ struct Mount
// multiple archives per dir support is required for patches. // multiple archives per dir support is required for patches.
Mount(const char* _v_mount_point, const char* _p_real_path, uint _pri) 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), : v_mount_point(v_mount_point_), p_real_path(p_real_path_),
dir_loc(0, _v_mount_point, _p_real_path, _pri), archive_locs() 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; typedef std::list<Mount> Mounts;
@ -1005,6 +1020,7 @@ TIMER(remount);
const char* v_mount_point = m.v_mount_point.c_str(); const char* v_mount_point = m.v_mount_point.c_str();
const char* p_real_path = m.p_real_path.c_str(); const char* p_real_path = m.p_real_path.c_str();
const int flags = m.flags;
const uint pri = m.pri; const uint pri = m.pri;
TLoc* dir_loc = &m.dir_loc; TLoc* dir_loc = &m.dir_loc;
TLocs& archive_locs = m.archive_locs; TLocs& archive_locs = m.archive_locs;
@ -1012,7 +1028,7 @@ TIMER(remount);
// callers have a tendency to forget required trailing '/'; // callers have a tendency to forget required trailing '/';
// complain if it's not there, unless path = "" (root dir). // complain if it's not there, unless path = "" (root dir).
#ifndef NDEBUG #ifndef NDEBUG
size_t len = strlen(v_mount_point); const size_t len = strlen(v_mount_point);
if(len && v_mount_point[len-1] != '/') if(len && v_mount_point[len-1] != '/')
debug_warn("remount: path doesn't end in '/'"); debug_warn("remount: path doesn't end in '/'");
#endif #endif
@ -1020,9 +1036,12 @@ TIMER(remount);
TDir* dir; TDir* dir;
CHECK_ERR(tree_lookup_dir(v_mount_point, &dir, LF_CREATE_MISSING)); 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). // add all loose files and subdirectories (recursive).
// also mounts all archives in p_real_path and adds to archive_locs. // 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. // <pri>(ority) is not lower.
// all archives in <p_real_path> are also mounted, in alphabetical order. // 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. // 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. // make sure it's not already mounted, i.e. in mounts.
// also prevents mounting a parent directory of a previously mounted // 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; 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 // actually mount the entry
Mount& m = mounts.back(); Mount& m = mounts.back();

View File

@ -39,6 +39,18 @@
// in English: '/' as path separator; trailing '/' required for dir names; // in English: '/' as path separator; trailing '/' required for dir names;
// no leading '/', since "" is the root dir. // 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>, // mount <p_real_dir> into the VFS at <vfs_mount_point>,
// which is created if it does not yet exist. // which is created if it does not yet exist.
@ -46,8 +58,10 @@
// <pri>(ority) is not lower. // <pri>(ority) is not lower.
// all archives in <p_real_dir> are also mounted, in alphabetical order. // 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. // 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. // rebuild the VFS, i.e. re-mount everything. open files are not affected.
// necessary after loose files or directories change, so that the VFS // 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"\ // display_startup_error(L"error setting current directory.\n"\
// L"argv[0] is probably incorrect. please start the game via command-line."); // L"argv[0] is probably incorrect. please start the game via command-line.");
vfs_mount("", "mods/official", 0); vfs_mount("", "mods/official", VFS_MOUNT_RECURSIVE|VFS_MOUNT_ARCHIVES);
vfs_mount("screenshots/", "screenshots", 0); vfs_mount("screenshots/", "screenshots");
vfs_mount("profiles/", "profiles", 0); vfs_mount("profiles/", "profiles");
// don't try vfs_display yet: SDL_Init hasn't yet redirected stdout // don't try vfs_display yet: SDL_Init hasn't yet redirected stdout
} }