219 lines
5.9 KiB
C++
219 lines
5.9 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "filesystem/filesystem.h"
|
|
#include "filesystem/io_handle.h"
|
|
#include "log/log.h"
|
|
|
|
|
|
#if __PLATFORM_POSIX__
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#elif __PLATFORM_WINDOWS__
|
|
#include <direct.h>
|
|
#endif
|
|
|
|
#include "filesystem/io_cfile.h"
|
|
#include "memory/nauto_ptr.h"
|
|
|
|
|
|
using GS::String;
|
|
using namespace GS::IO;
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Filesystem::Exists(const char *uri) const
|
|
{
|
|
AutoPtr <Handle> h(Open(uri));
|
|
return h.IsValid();
|
|
}
|
|
size_t Filesystem::FileSize(const char *uri) const
|
|
{
|
|
AutoPtr <Handle> h(Open(uri));
|
|
return h.IsNull() ? 0 : h->GetSize();
|
|
}
|
|
bool Filesystem::FileLoad(const char *uri, GS::Array <char> &buffer, bool verbose) const
|
|
{
|
|
AutoPtr <Handle> h(Open(uri));
|
|
if (h.IsNull())
|
|
{
|
|
if (verbose)
|
|
__LOG_W__ << "Failed to open '" << uri << "'.\n";
|
|
return false;
|
|
}
|
|
|
|
// Warning: Do not load through IO::Base::FileLoad. That would create another handle!
|
|
size_t size = h->GetSize();
|
|
if (!buffer.Allocate(size))
|
|
__ERR__(__LOG_W__ << "Failed to allocate memory to load '" << uri << "'.\n", false)
|
|
|
|
return asbool(h->Read(buffer.c_ptr(), size) == size);
|
|
}
|
|
bool Filesystem::FileSave(const char *uri, const GS::Array <char> &buffer) const
|
|
{
|
|
AutoPtr <Handle> h(Open(uri, ModeWrite));
|
|
if (h.IsNull())
|
|
__ERR__(__LOG_W__ << "Failed to open '" << uri << "'.\n", false)
|
|
return asbool(h->Write(buffer.c_ptr(), buffer.GetSize()) == buffer.GetSize());
|
|
}
|
|
bool Filesystem::FileCopy(const char *src, const char *dst) const
|
|
{
|
|
Array <char> buffer;
|
|
return FileLoad(src, buffer) && FileSave(dst, buffer);
|
|
}
|
|
bool Filesystem::FileMove(const char *src, const char *dst) const
|
|
{
|
|
Array <char> buffer;
|
|
return FileLoad(src, buffer) && FileSave(dst, buffer) && Delete(src);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
String Filesystem::MapToAbsolute(const char *uri) const
|
|
{
|
|
String _uri(uri);
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (_uri.StartsWith(m->mount_point))
|
|
return m->io_sys->MapToAbsolute(_uri.Mid(m->mount_point.Len())).CleanFilePath();
|
|
|
|
ListForeachPtr(Base *, i, root_mount)
|
|
{
|
|
AutoPtr <Handle> h(i->Open(_uri));
|
|
if (h.IsValid())
|
|
return i->MapToAbsolute(_uri).CleanFilePath();
|
|
}
|
|
return _uri;
|
|
}
|
|
String Filesystem::StripRootPath(const char *path) const
|
|
{
|
|
String _path(path);
|
|
_path.FileCleanName();
|
|
ListForeachPtr(Base *, i, root_mount)
|
|
{
|
|
String rpath = i->MapToRelative(_path);
|
|
if (!rpath.IsEmpty())
|
|
if (rpath != _path)
|
|
return rpath[0] == '/' ? rpath.Mid(1) : rpath; // Ensure no leading '/' remains.
|
|
}
|
|
return _path;
|
|
}
|
|
bool Filesystem::Mount(Base *io_sys, const char *mount_point)
|
|
{
|
|
if (mount_point)
|
|
{
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (m->mount_point == mount_point)
|
|
{
|
|
delete io_sys;
|
|
return false;
|
|
}
|
|
|
|
|
|
return asbool(mount_list.Prepend(new MountPoint(mount_point, io_sys)));
|
|
}
|
|
else
|
|
{
|
|
ListForeachPtr(Base *, i, root_mount)
|
|
if (i == io_sys)
|
|
__ERR__(__LOG_E__ << "Cannot mount IO system twice as root.\n", false)
|
|
|
|
return asbool(root_mount.Prepend(io_sys));
|
|
}
|
|
}
|
|
void Filesystem::Unmount(const char *mount_point)
|
|
{ Unmount(GetIOSystem(mount_point)); }
|
|
void Filesystem::Unmount(Base *io_sys)
|
|
{
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (m->io_sys.c_ptr() == io_sys)
|
|
mount_list.Remove(m);
|
|
ListForeachPtr(Base *, i, root_mount)
|
|
if (i == io_sys)
|
|
root_mount.Remove(i);
|
|
}
|
|
void Filesystem::UnmountAll()
|
|
{
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
mount_list.Remove(m);
|
|
while (List <Base *> ::Item *m = root_mount.GetRoot())
|
|
root_mount.Remove(m);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Base *Filesystem::GetIOSystem(const char *mount_point) const
|
|
{
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (m->mount_point == mount_point)
|
|
return m->io_sys;
|
|
return NULL;
|
|
}
|
|
const char *Filesystem::GetMountPoint(const Base *io_sys) const
|
|
{
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (m->io_sys == io_sys)
|
|
return m->mount_point;
|
|
return NULL;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Handle *Filesystem::Open(const char *uri, Mode mode) const
|
|
{
|
|
String _uri(uri);
|
|
|
|
if (_uri.IsEmpty())
|
|
return NULL;
|
|
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (_uri.StartsWith(m->mount_point))
|
|
return m->io_sys->Open(_uri.Mid(m->mount_point.Len()), mode);
|
|
ListForeachPtr(Base *, i, root_mount)
|
|
if (Handle *h = i->Open(uri, mode))
|
|
return h;
|
|
|
|
return NULL;
|
|
}
|
|
void Filesystem::Close(Handle *h) const
|
|
{
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (m->io_sys.c_ptr() == h->GetIOSystem())
|
|
m->io_sys->Close(h);
|
|
ListForeachPtr(Base *, i, root_mount)
|
|
if (i == h->GetIOSystem())
|
|
i->Close(h);
|
|
}
|
|
bool Filesystem::Delete(const char *uri) const
|
|
{
|
|
AutoPtr <Handle> h(Open(uri));
|
|
if (h.IsValid())
|
|
{
|
|
Base *io_sys = h->GetIOSystem();
|
|
h = NULL;
|
|
return io_sys->Delete(uri);
|
|
}
|
|
else
|
|
return asbool(unlink(uri) == 0);
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Filesystem::MkDir(const char *path) const
|
|
{
|
|
String _path(path);
|
|
|
|
if (_path.IsEmpty())
|
|
return false;
|
|
|
|
ListForeachPtr(MountPoint *, m, mount_list)
|
|
if (_path.StartsWith(m->mount_point))
|
|
return m->io_sys->MkDir(_path.Mid(m->mount_point.Len()));
|
|
|
|
// [EJ] No creation on a root filesystem here!
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|