1
0
forked from 0ad/0ad

# VFS: add support for redirecting writes of files that are in archives to writable mod directory (required for editor)

This was SVN commit r3818.
This commit is contained in:
janwas 2006-04-25 17:35:35 +00:00
parent 11e53a3ce0
commit 2bd3708339
8 changed files with 88 additions and 9 deletions

View File

@ -438,8 +438,9 @@ ERR(-100330, ERR_IO, "Error during IO")
ERR(-100331, ERR_EOF, "Reading beyond end of file")
// .. mount
ERR(-100340, ERR_ALREADY_MOUNTED, "Directory (tree) already mounted")
ERR(-100341, ERR_INVALID_MOUNT_TYPE, "Invalid mount type (memory corruption?)")
ERR(-100342, ERR_ROOT_DIR_ALREADY_SET, "Attempting to set FS root dir more than once")
ERR(-100341, ERR_NOT_MOUNTED, "Specified directory is not mounted")
ERR(-100342, ERR_INVALID_MOUNT_TYPE, "Invalid mount type (memory corruption?)")
ERR(-100343, ERR_ROOT_DIR_ALREADY_SET, "Attempting to set FS root dir more than once")
// .. misc
ERR(-100350, ERR_UNKNOWN_CMETHOD, "Unknown/unsupported compression method")
ERR(-100351, ERR_IS_COMPRESSED, "Invalid operation for a compressed file")

View File

@ -269,9 +269,13 @@ enum FileFlags
// promising they will set atom_fn).
FILE_DONT_SET_FN = 0x80,
// sum of all flags above. used when validating flag parameters and
// by zip.cpp because its flags live alongside these.
FILE_FLAG_ALL = 0xFF
// (only relevant for VFS) file will be written into the
// appropriate subdirectory of the mount point established by
// vfs_mod_set_write_target. see documentation there.
FILE_WRITE_TO_MOD = FILE_WRITE|0x100,
// sum of all flags above. used when validating flag parameters.
FILE_FLAG_ALL = 0x1FF
};

View File

@ -360,9 +360,7 @@ LibError vfs_stat(const char* V_path, struct stat* s)
}
//-----------------------------------------------------------------------------
struct VFile
{
@ -423,6 +421,9 @@ static LibError VFile_reload(VFile* vf, const char* V_path, Handle)
return err;
}
if(flags & FILE_WRITE_TO_MOD)
RETURN_ERR(set_mount_to_mod_target(tf));
RETURN_ERR(xfile_open(V_path, flags, tf, &vf->f));
stats_open(vf->f.atom_fn, vf->f.size);

View File

@ -288,6 +288,15 @@ extern LibError vfs_mount(const char* V_mount_point, const char* P_real_dir, uin
// unmount a previously mounted item, and rebuild the VFS afterwards.
extern LibError vfs_unmount(const char* name);
// set current "mod write directory" to P_target_dir, which must
// already have been mounted into the VFS.
// all files opened for writing with the FILE_WRITE_TO_MOD flag set will
// be written into the appropriate subdirectory of this mount point.
//
// this allows e.g. the editor to write files that are already
// stored in archives, which are read-only.
extern LibError vfs_mod_set_write_target(const char* P_target_dir);
//
// directory entry

View File

@ -676,7 +676,7 @@ struct IsArchiveMount
{
bool operator()(const Mount& m) const
{
return (m.archive > 0);
return (m.type == MT_ARCHIVE);
}
};
@ -740,6 +740,60 @@ LibError mount_make_vfs_path(const char* P_path, char* V_path)
}
static const Mount* mod_target;
// set current "mod write directory" to P_target_dir, which must
// already have been mounted into the VFS.
// all files opened for writing with the FILE_WRITE_TO_MOD flag set will
// be written into the appropriate subdirectory of this mount point.
//
// this allows e.g. the editor to write files that are already
// stored in archives, which are read-only.
LibError vfs_mod_set_write_target(const char* P_target_dir)
{
for(MountIt it = mounts.begin(); it != mounts.end(); ++it)
{
const Mount& m = *it;
// skip if not a directory mounting
if(m.type != MT_FILE)
continue;
// found it in list of mounted dirs
if(!strcmp(m.P_name.c_str(), P_target_dir))
{
mod_target = &m;
return ERR_OK;
}
}
WARN_RETURN(ERR_NOT_MOUNTED);
}
// 'relocate' tf to the mounting established by vfs_mod_set_write_target.
// call if <tf> is being opened with FILE_WRITE_TO_MOD flag set.
LibError set_mount_to_mod_target(TFile* tf)
{
if(!mod_target)
WARN_RETURN(ERR_NOT_MOUNTED);
tfile_set_mount(tf, mod_target);
// invalidate the previous values. we don't need to be clever and
// set size to that of the file in the new mod_target mount point.
// this is because we're only called for files that are being
// opened for writing, which will change these values anyway.
tree_update_file(tf, 0, 0);
return ERR_OK;
}
void mount_init()
{
tree_init();

View File

@ -95,6 +95,10 @@ extern LibError mount_populate(TDir* td, RealDir* rd);
// because this call leaves the VFS in limbo!!
extern void mount_release_all_archives();
// 'relocate' tf to the mounting established by vfs_mod_set_write_target.
// call if <tf> is being opened with FILE_WRITE_TO_MOD flag set.
extern LibError set_mount_to_mod_target(TFile* tf);
// 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

@ -702,6 +702,11 @@ const char* tfile_get_atom_fn(const TFile* tf)
void tfile_set_mount(TFile* tf, const Mount* m)
{
tf->m = m;
}
void tree_update_file(TFile* tf, off_t size, time_t mtime)
{
tf->size = size;

View File

@ -113,6 +113,7 @@ extern const Mount* tfile_get_mount(const TFile* tf);
extern uintptr_t tfile_get_memento(const TFile* tf);
extern const char* tfile_get_atom_fn(const TFile* tf);
extern void tfile_set_mount(TFile* tf, const Mount* m);
extern void tree_update_file(TFile* tf, off_t size, time_t mtime);
struct RealDir;