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:
parent
e632c0ff1d
commit
fba99c3414
@ -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)¶ms);
|
file_enum(p_path, dirent_cb, (uintptr_t)¶ms);
|
||||||
|
|
||||||
// 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();
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user