1
0
Fork 0
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:
fgenesis 2014-04-07 02:25:58 +02:00
parent 6203bc7ce4
commit b437a7cb2c
13 changed files with 84 additions and 108 deletions

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

View file

@ -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:

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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;
}

View file

@ -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. */

View file

@ -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)

View file

@ -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)