mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-15 05:59:16 +00:00
Fix ttvfs bugs, sync with dev repo
This commit is contained in:
parent
6203bc7ce4
commit
b437a7cb2c
13 changed files with 84 additions and 108 deletions
|
@ -2804,19 +2804,13 @@ bool DSQ::mountModPackage(const std::string& pkg)
|
|||
{
|
||||
// Load archive only if no such directory exists already (prevent loading multiple times)
|
||||
vd = vfs.AddArchive(pkg.c_str());
|
||||
if(vd)
|
||||
debugLog("Package: Loaded file " + pkg);
|
||||
else
|
||||
if(!vd)
|
||||
{
|
||||
debugLog("Package: Unable to load " + pkg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!vfs.Mount(pkg.c_str(), mod.getBaseModPath().c_str()))
|
||||
{
|
||||
debugLog("Package: Failed to mount: " + pkg);
|
||||
return false;
|
||||
}
|
||||
vfs.Mount(pkg.c_str(), mod.getBaseModPath().c_str());
|
||||
debugLog("Package: Mounted " + pkg + " as archive in _mods");
|
||||
return true;
|
||||
#else
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
// Define this to allow dealing with files > 4 GB, using non-standard functions.
|
||||
// This may or may not work with your platform/compiler, good luck.
|
||||
#define VFS_LARGEFILE_SUPPORT
|
||||
//#define VFS_LARGEFILE_SUPPORT
|
||||
|
||||
// Define this to make all operations case insensitive.
|
||||
// Windows systems generally don't care much, but for Linux and Mac this can be used
|
||||
|
|
|
@ -21,56 +21,22 @@ DirBase::~DirBase()
|
|||
{
|
||||
}
|
||||
|
||||
File *DirBase::getFile(const char *fn, bool lazyLoad /* = true */)
|
||||
File *DirBase::getFile(const char *fn)
|
||||
{
|
||||
while(fn[0] == '.' && fn[1] == '/') // skip ./
|
||||
fn += 2;
|
||||
const char *slashpos = strchr(fn, '/');
|
||||
if(!slashpos)
|
||||
return getFileByName(fn, true);
|
||||
|
||||
char *slashpos = (char *)strchr(fn, '/');
|
||||
const size_t len = slashpos - fn;
|
||||
char *dirname = (char*)VFS_STACK_ALLOC(len + 1);
|
||||
memcpy(dirname, fn, len);
|
||||
dirname[len] = 0;
|
||||
|
||||
// if there is a '/' in the string, descend into subdir and continue there
|
||||
if(slashpos)
|
||||
{
|
||||
// "" (the empty directory name) is allowed, so we can't return 'this' when hitting an empty string the first time.
|
||||
// This whole mess is required for absolute unix-style paths ("/home/foo/..."),
|
||||
// which, to integrate into the tree properly, sit in the root directory's ""-subdir.
|
||||
// FIXME: Bad paths (double-slashes and the like) need to be normalized elsewhere, currently!
|
||||
|
||||
size_t len = strlen(fn);
|
||||
char *dup = (char*)VFS_STACK_ALLOC(len + 1);
|
||||
memcpy(dup, fn, len + 1); // also copy the null-byte
|
||||
slashpos = dup + (slashpos - fn); // use direct offset, not to have to recount again the first time
|
||||
DirBase *subdir = this;
|
||||
const char *ptr = dup;
|
||||
|
||||
goto pos_known;
|
||||
do
|
||||
{
|
||||
ptr = slashpos + 1;
|
||||
while(ptr[0] == '.' && ptr[1] == '/') // skip ./
|
||||
ptr += 2;
|
||||
slashpos = (char *)strchr(ptr, '/');
|
||||
if(!slashpos)
|
||||
break;
|
||||
|
||||
pos_known:
|
||||
*slashpos = 0;
|
||||
subdir = subdir->getDirByName(ptr, true, true);
|
||||
}
|
||||
while(subdir);
|
||||
VFS_STACK_FREE(dup);
|
||||
if(!subdir)
|
||||
return NULL;
|
||||
// restore pointer into original string, by offset
|
||||
ptr = fn + (ptr - dup);
|
||||
return subdir->getFileByName(ptr, lazyLoad);
|
||||
}
|
||||
|
||||
// no subdir? file must be in this dir now.
|
||||
return getFileByName(fn, lazyLoad);
|
||||
File *f = getFileFromSubdir(dirname, slashpos + 1);
|
||||
VFS_STACK_FREE(dirname);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
DirBase *DirBase::getDir(const char *subdir, bool forceCreate /* = false */, bool lazyLoad /* = true */, bool useSubtrees /* = true */)
|
||||
{
|
||||
SkipSelfPath(subdir);
|
||||
|
@ -203,7 +169,6 @@ File *Dir::getFileByName(const char *fn, bool lazyLoad /* = true */)
|
|||
return NULL;
|
||||
|
||||
// Lazy-load file if it's not in the tree yet
|
||||
// TODO: get rid of alloc
|
||||
std::string fn2 = joinPath(fullname(), GetBaseNameFromPath(fn));
|
||||
File *f = _loader->Load(fn2.c_str(), fn2.c_str());
|
||||
if(f)
|
||||
|
@ -267,7 +232,6 @@ bool Dir::addRecursive(File *f, size_t skip /* = 0 */)
|
|||
{
|
||||
char *dirname = (char*)VFS_STACK_ALLOC(prefixLen);
|
||||
--prefixLen; // -1 to strip the trailing '/'. That's the position where to put the terminating null byte.
|
||||
++skip;
|
||||
memcpy(dirname, f->fullname() + skip, prefixLen); // copy trailing null byte
|
||||
dirname[prefixLen] = 0;
|
||||
vdir = safecastNonNull<Dir*>(getDir(dirname, true));
|
||||
|
@ -313,6 +277,12 @@ DirBase *Dir::getDirByName(const char *dn, bool lazyLoad /* = true */, bool useS
|
|||
return sub;
|
||||
}
|
||||
|
||||
File *Dir::getFileFromSubdir(const char *subdir, const char *file)
|
||||
{
|
||||
Dir *d = safecast<Dir*>(getDirByName(subdir, true, false)); // useSubtrees is irrelevant here
|
||||
return d ? d->getFile(file) : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----- DiskDir start here -----
|
||||
|
@ -337,12 +307,7 @@ void DiskDir::load()
|
|||
GetFileList(fullname(), li);
|
||||
for(StringList::iterator it = li.begin(); it != li.end(); ++it)
|
||||
{
|
||||
// TODO: use stack alloc
|
||||
std::string tmp = fullname();
|
||||
tmp += '/';
|
||||
tmp += *it;
|
||||
|
||||
DiskFile *f = new DiskFile(tmp.c_str());
|
||||
DiskFile *f = new DiskFile(joinPath(fullname(), it->c_str()).c_str());
|
||||
_files[f->name()] = f;
|
||||
}
|
||||
|
||||
|
@ -350,12 +315,8 @@ void DiskDir::load()
|
|||
GetDirList(fullname(), li, 0);
|
||||
for(StringList::iterator it = li.begin(); it != li.end(); ++it)
|
||||
{
|
||||
// TODO: use stack alloc
|
||||
std::string full(fullname());
|
||||
full += '/';
|
||||
full += *it; // GetDirList() always returns relative paths
|
||||
|
||||
Dir *d = createNew(full.c_str());
|
||||
// GetDirList() returns relative paths, so need to join
|
||||
Dir *d = createNew(joinPath(fullname(), it->c_str()).c_str());
|
||||
_subdirs[d->name()] = d;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
|
||||
/** Returns a file for this dir's subtree. Descends if necessary.
|
||||
Returns NULL if the file is not found. */
|
||||
File *getFile(const char *fn, bool lazyLoad = true);
|
||||
File *getFile(const char *fn);
|
||||
|
||||
/** Returns a subdir, descends if necessary. If forceCreate is true,
|
||||
create directory tree if it does not exist, and return the originally requested
|
||||
|
@ -90,6 +90,8 @@ public:
|
|||
virtual File *getFileByName(const char *fn, bool lazyLoad = true) = 0;
|
||||
virtual DirBase *getDirByName(const char *fn, bool lazyLoad = true, bool useSubtrees = true);
|
||||
|
||||
virtual File *getFileFromSubdir(const char *subdir, const char *file) = 0;
|
||||
|
||||
/** Iterate over all files or directories, calling a callback function,
|
||||
optionally with additional userdata. If safe is true, iterate over a copy.
|
||||
This is useful if the callback function modifies the tree, e.g.
|
||||
|
@ -135,6 +137,7 @@ public:
|
|||
bool _addToView(char *path, DirView& view);
|
||||
DirBase *getDirByName(const char *dn, bool lazyLoad = true, bool useSubtrees = true);
|
||||
File *getFileByName(const char *fn, bool lazyLoad = true);
|
||||
File *getFileFromSubdir(const char *subdir, const char *file);
|
||||
|
||||
|
||||
protected:
|
||||
|
|
|
@ -42,6 +42,9 @@ void InternalDir::close()
|
|||
|
||||
void InternalDir::_addMountDir(CountedPtr<DirBase> d)
|
||||
{
|
||||
if(d.content() == this)
|
||||
return;
|
||||
|
||||
// move to end of vector if already mounted
|
||||
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
|
||||
if(*it == d)
|
||||
|
@ -162,7 +165,15 @@ bool InternalDir::_addToView(char *path, DirView& view)
|
|||
return added;
|
||||
}
|
||||
|
||||
File *InternalDir::getFileFromSubdir(const char *subdir, const char *file)
|
||||
{
|
||||
for(MountedDirs::reverse_iterator it = _mountedDirs.rbegin(); it != _mountedDirs.rend(); ++it)
|
||||
if(File* f = (*it)->getFileFromSubdir(subdir, file))
|
||||
return f;
|
||||
|
||||
InternalDir *d = safecast<InternalDir*>(DirBase::getDirByName(subdir, false, false)); // vcall not required here
|
||||
return d ? d->getFile(file) : NULL;
|
||||
}
|
||||
|
||||
|
||||
VFS_NAMESPACE_END
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
void forEachDir(DirEnumCallback f, void *user = NULL, bool safe = false);
|
||||
File *getFileByName(const char *fn, bool lazyLoad = true);
|
||||
DirBase *getDirByName(const char *fn, bool lazyLoad = true, bool useSubtrees = true);
|
||||
File *getFileFromSubdir(const char *subdir, const char *file);
|
||||
void close();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -65,9 +65,12 @@ bool DirView::_addToView(char *path, DirView& view)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void __test__()
|
||||
File *DirView::getFileFromSubdir(const char *subdir, const char *file)
|
||||
{
|
||||
new DirView;
|
||||
for(ViewList::reverse_iterator it = _view.rbegin(); it != _view.rend(); ++it)
|
||||
if(File* f = (*it)->getFileFromSubdir(subdir, file))
|
||||
return f;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VFS_NAMESPACE_END
|
||||
|
|
|
@ -13,16 +13,17 @@ class DirView : public DirBase
|
|||
{
|
||||
public:
|
||||
DirView();
|
||||
~DirView();
|
||||
virtual ~DirView();
|
||||
void init(const char *);
|
||||
void add(DirBase *);
|
||||
|
||||
virtual File *getFileByName(const char *fn, bool lazyLoad = true);
|
||||
virtual void forEachDir(DirEnumCallback f, void *user = NULL, bool safe = false);
|
||||
virtual void forEachFile(FileEnumCallback f, void *user = NULL, bool safe = false);
|
||||
File *getFileByName(const char *fn, bool lazyLoad = true);
|
||||
void forEachDir(DirEnumCallback f, void *user = NULL, bool safe = false);
|
||||
void forEachFile(FileEnumCallback f, void *user = NULL, bool safe = false);
|
||||
File *getFileFromSubdir(const char *subdir, const char *file);
|
||||
|
||||
virtual const char *getType() const { return "DirView"; }
|
||||
virtual DirBase *createNew(const char *dir) const { return NULL; }
|
||||
const char *getType() const { return "DirView"; }
|
||||
DirBase *createNew(const char *dir) const { return NULL; }
|
||||
|
||||
bool _addToView(char *path, DirView& view);
|
||||
|
||||
|
|
|
@ -121,13 +121,16 @@ Dir *DiskLoader::LoadDir(const char *fn, const char * /*ignored*/)
|
|||
char *t = (char*)VFS_STACK_ALLOC(s+1);
|
||||
memcpy(t, fn, s+1); // copy terminating '\0' as well
|
||||
if(findFileHarder(&t[0])) // fixes the filename on the way
|
||||
{
|
||||
fn = &t[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = safecastNonNull<DiskDir*>(getRoot()->getDir(fn, true, false));
|
||||
|
||||
#if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
|
||||
VFS_STACK_FREE(t);
|
||||
#endif
|
||||
|
||||
return safecastNonNull<DiskDir*>(getRoot()->getDir(fn, true, false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
VFS_NAMESPACE_END
|
||||
|
|
|
@ -51,7 +51,6 @@ Root::Root()
|
|||
|
||||
Root::~Root()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Root::Clear()
|
||||
|
@ -63,32 +62,27 @@ void Root::Clear()
|
|||
archLdrs.clear();
|
||||
}
|
||||
|
||||
bool Root::Mount(const char *src, const char *dest)
|
||||
void Root::Mount(const char *src, const char *dest)
|
||||
{
|
||||
return AddVFSDir(GetDir(src, true), dest);
|
||||
}
|
||||
|
||||
bool Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */)
|
||||
void Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */)
|
||||
{
|
||||
if(!dir)
|
||||
return false;
|
||||
if(!subdir)
|
||||
subdir = dir->fullname();
|
||||
|
||||
InternalDir *into = safecastNonNull<InternalDir*>(merged->getDir(subdir, true, true, false));
|
||||
into->_addMountDir(dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Root::Unmount(const char *src, const char *dest)
|
||||
{
|
||||
DirBase *vdsrc = GetDir(src, false);
|
||||
InternalDir *vddest = safecastNonNull<InternalDir*>(GetDir(dest, false));
|
||||
InternalDir *vddest = safecast<InternalDir*>(GetDir(dest, false));
|
||||
if(!vdsrc || !vddest)
|
||||
return false;
|
||||
|
||||
vddest->_removeMountDir(vdsrc); // FIXME: verify this works
|
||||
vddest->_removeMountDir(vdsrc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,17 +96,20 @@ void Root::AddArchiveLoader(VFSArchiveLoader *ldr)
|
|||
{
|
||||
archLdrs.push_back(ldr);
|
||||
}
|
||||
|
||||
Dir *Root::AddArchive(const char *arch, void *opaque /* = NULL */)
|
||||
{
|
||||
File *af = GetFile(arch);
|
||||
if(!af)
|
||||
return AddArchive(GetFile(arch), arch, opaque);
|
||||
}
|
||||
|
||||
Dir *Root::AddArchive(File *file, const char *path /* = NULL */, void *opaque /* = NULL */)
|
||||
{
|
||||
if(!file || !file->open("rb"))
|
||||
return NULL;
|
||||
|
||||
Dir *ad = NULL;
|
||||
VFSLoader *fileLdr = NULL;
|
||||
for(ArchiveLoaderArray::iterator it = archLdrs.begin(); it != archLdrs.end(); ++it)
|
||||
if((ad = (*it)->Load(af, &fileLdr, opaque)))
|
||||
if((ad = (*it)->Load(file, &fileLdr, opaque)))
|
||||
break;
|
||||
if(!ad)
|
||||
return NULL;
|
||||
|
@ -120,7 +117,7 @@ Dir *Root::AddArchive(const char *arch, void *opaque /* = NULL */)
|
|||
if(fileLdr)
|
||||
loaders.push_back(fileLdr);
|
||||
|
||||
AddVFSDir(ad, arch);
|
||||
AddVFSDir(ad, path ? path : file->fullname());
|
||||
|
||||
return ad;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
/** Mount a directory in the tree to a different location. Requires a previous call to Prepare().
|
||||
This can be imagined like the contents of a directory appearing in a different location.
|
||||
Be careful not to create circles! */
|
||||
bool Mount(const char *src, const char *dest);
|
||||
void Mount(const char *src, const char *dest);
|
||||
|
||||
/** Drops a directory from the tree. Internally, this calls Reload(false),
|
||||
which is a heavy operation compared to Mount(). Be warned. */
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
add into the subdir stored in the Dir object. The tree will be extended if target dir does not exist.
|
||||
Files in the tree will be replaced if already existing.
|
||||
Like with Mount(); be careful not to create cycles. */
|
||||
bool AddVFSDir(DirBase *dir, const char *subdir = NULL);
|
||||
void AddVFSDir(DirBase *dir, const char *subdir = NULL);
|
||||
|
||||
/** Add an archive file to the tree, which can then be addressed like a folder,
|
||||
e.g. "path/to/example.zip/file.txt".
|
||||
|
@ -61,6 +61,7 @@ public:
|
|||
Read the comments in VFSArchiveLoader.h for an explanation how it works.
|
||||
If you have no idea, leave it NULL, because it can easily cause a crash if not used carefully. */
|
||||
Dir *AddArchive(const char *arch, void *opaque = NULL);
|
||||
Dir *AddArchive(File *file, const char *path = NULL, void *opaque = NULL);
|
||||
|
||||
/** Add a loader that can look for files on demand.
|
||||
Do not add more then once instance of a loader type. */
|
||||
|
|
|
@ -107,18 +107,19 @@ InStream::InStream(const char *fn)
|
|||
bool InStream::open(const char *fn)
|
||||
{
|
||||
ttvfs::File *vf = vfs->GetFile(fn);
|
||||
if(vf && vf->open("r"))
|
||||
if(!vf || !vf->open("r"))
|
||||
{
|
||||
size_t sz = (size_t)vf->size();
|
||||
std::string s;
|
||||
s.resize(sz);
|
||||
vf->read(&s[0], sz);
|
||||
str(s);
|
||||
vf->close();
|
||||
return true;
|
||||
setstate(std::ios::failbit);
|
||||
return false;
|
||||
}
|
||||
setstate(std::ios::failbit);
|
||||
return false;
|
||||
size_t sz = (size_t)vf->size();
|
||||
std::string s;
|
||||
s.resize(sz);
|
||||
size_t bytes = vf->read(&s[0], sz);
|
||||
s.resize(bytes);
|
||||
str(s);
|
||||
vf->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
int ttvfs_stdio_fsize(VFILE *f, size_t *sizep)
|
||||
|
|
|
@ -47,7 +47,7 @@ void ZipDir::load()
|
|||
_archiveHandle->openRead();
|
||||
|
||||
const unsigned int files = mz_zip_reader_get_num_files(MZ);
|
||||
const size_t len = fullnameLen();
|
||||
const size_t len = fullnameLen() + 1; // +1 for trailing '/' when used as path name in addRecursive()
|
||||
|
||||
mz_zip_archive_file_stat fs;
|
||||
for (unsigned int i = 0; i < files; ++i)
|
||||
|
|
Loading…
Reference in a new issue