/* ----------------------------------------------------------------------------- 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 #include #elif __PLATFORM_WINDOWS__ #include #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 h(Open(uri)); return h.IsValid(); } size_t Filesystem::FileSize(const char *uri) const { AutoPtr h(Open(uri)); return h.IsNull() ? 0 : h->GetSize(); } bool Filesystem::FileLoad(const char *uri, GS::Array &buffer, bool verbose) const { AutoPtr 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 &buffer) const { AutoPtr 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 buffer; return FileLoad(src, buffer) && FileSave(dst, buffer); } bool Filesystem::FileMove(const char *src, const char *dst) const { Array 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 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 ::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 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; } //------------------------------------------------------------------------------