diff options
-rw-r--r-- | backends/cloud/dropbox/dropboxstorage.cpp | 6 | ||||
-rw-r--r-- | backends/fs/abstract-fs.h | 9 | ||||
-rw-r--r-- | backends/fs/posix/posix-fs.cpp | 24 | ||||
-rw-r--r-- | backends/fs/posix/posix-fs.h | 1 | ||||
-rw-r--r-- | backends/fs/windows/windows-fs.cpp | 32 | ||||
-rw-r--r-- | backends/fs/windows/windows-fs.h | 1 | ||||
-rw-r--r-- | common/file.cpp | 18 | ||||
-rw-r--r-- | common/file.h | 2 |
8 files changed, 87 insertions, 6 deletions
diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 38ad12d94b..e5041466e9 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -103,7 +103,7 @@ Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { void DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { Common::DumpFile *f = new Common::DumpFile(); - if (!f->open(localPath)) { + if (!f->open(localPath, true)) { warning("DropboxStorage: unable to open file to download into"); if (callback) (*callback)(false); delete f; @@ -116,8 +116,8 @@ void DropboxStorage::download(Common::String remotePath, Common::String localPat void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" is root in Dropbox, not "/" - //listDirectory("", new Common::Callback<DropboxStorage, Common::Array<StorageFile> >(this, &DropboxStorage::printFiles), true); - download("/remote/test.jpg", "local/test.jpg", 0); + //this must create all these directories: + download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); } void DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h index dcfdc08975..24286b649d 100644 --- a/backends/fs/abstract-fs.h +++ b/backends/fs/abstract-fs.h @@ -191,6 +191,15 @@ public: * @return pointer to the stream object, 0 in case of a failure */ virtual Common::WriteStream *createWriteStream() = 0; + + /** + * Creates a file referred by this node. + * + * @param isDirectory true if created file must be a directory + * + * @return true if file is created successfully + */ + virtual bool create(bool isDirectory) = 0; }; diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp index 1a6c4e40a5..d388f306fd 100644 --- a/backends/fs/posix/posix-fs.cpp +++ b/backends/fs/posix/posix-fs.cpp @@ -252,6 +252,30 @@ Common::WriteStream *POSIXFilesystemNode::createWriteStream() { return StdioStream::makeFromPath(getPath(), true); } +bool POSIXFilesystemNode::create(bool isDirectory) { + bool success; + + if (isDirectory) { + success = mkdir(_path.c_str(), 0755) == 0; + } else { + success = creat(_path.c_str(), 0755) != -1; + } + + if (success) { + setFlags(); + if (_isValid) { + if (_isDirectory != isDirectory) warning("failed to create %s: got %s", isDirectory ? "directory" : "file", _isDirectory ? "directory" : "file"); + return _isDirectory == isDirectory; + } + + warning("POSIXFilesystemNode: %s() was a success, but stat indicates there is no such %s", + isDirectory ? "mkdir" : "creat", isDirectory ? "directory" : "file"); + return false; + } + + return false; +} + namespace Posix { bool assureDirectoryExists(const Common::String &dir, const char *prefix) { diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h index 0703ac5bf5..4ebce7e9d9 100644 --- a/backends/fs/posix/posix-fs.h +++ b/backends/fs/posix/posix-fs.h @@ -73,6 +73,7 @@ public: virtual Common::SeekableReadStream *createReadStream(); virtual Common::WriteStream *createWriteStream(); + virtual bool create(bool isDirectory); private: /** diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp index 49549b83cb..b43686f911 100644 --- a/backends/fs/windows/windows-fs.cpp +++ b/backends/fs/windows/windows-fs.cpp @@ -244,4 +244,36 @@ Common::WriteStream *WindowsFilesystemNode::createWriteStream() { return StdioStream::makeFromPath(getPath(), true); } +bool WindowsFilesystemNode::create(bool isDirectory) { + bool success; + + if (isDirectory) { + success = CreateDirectory(toUnicode(_path.c_str()), NULL) != 0; + } else { + success = CreateFile(toUnicode(_path.c_str()), GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) != INVALID_HANDLE_VALUE; + } + + if (success) { + //this piece is copied from constructor, it checks that file exists and detects whether it's a directory + DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str())); + if (fileAttribs != INVALID_FILE_ATTRIBUTES) { + _isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0); + _isValid = true; + // Add a trailing slash, if necessary. + if (_isDirectory && _path.lastChar() != '\\') { + _path += '\\'; + } + + if (_isDirectory != isDirectory) warning("failed to create %s: got %s", isDirectory ? "directory" : "file", _isDirectory ? "directory" : "file"); + return _isDirectory == isDirectory; + } + + warning("WindowsFilesystemNode: Create%s() was a success, but GetFileAttributes() indicates there is no such %s", + isDirectory ? "Directory" : "File", isDirectory ? "directory" : "file"); + return false; + } + + return false; +} + #endif //#ifdef WIN32 diff --git a/backends/fs/windows/windows-fs.h b/backends/fs/windows/windows-fs.h index d06044603a..7c9f2c1e1a 100644 --- a/backends/fs/windows/windows-fs.h +++ b/backends/fs/windows/windows-fs.h @@ -88,6 +88,7 @@ public: virtual Common::SeekableReadStream *createReadStream(); virtual Common::WriteStream *createWriteStream(); + virtual bool create(bool isDirectory); private: /** diff --git a/common/file.cpp b/common/file.cpp index 4d9c630076..52b66bd2f4 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -25,6 +25,8 @@ #include "common/file.h" #include "common/fs.h" #include "common/textconsole.h" +#include "common/system.h" +#include "backends/fs/fs-factory.h" namespace Common { @@ -149,11 +151,23 @@ DumpFile::~DumpFile() { close(); } -bool DumpFile::open(const String &filename) { +bool DumpFile::open(const String &filename, bool createPath) { assert(!filename.empty()); assert(!_handle); - FSNode node(filename); + if (createPath) { + for (uint32 i = 0; i < filename.size(); ++i) { + if (filename[i] == '/' || filename[i] == '\\') { + Common::String subpath = filename; + subpath.erase(i); + AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(subpath); + if (node->exists()) continue; + if (!node->create(true)) warning("DumpFile: unable to create directories from path prefix"); + } + } + } + + FSNode node(filename); return open(node); } diff --git a/common/file.h b/common/file.h index 3d174834e9..8ad6249d6d 100644 --- a/common/file.h +++ b/common/file.h @@ -143,7 +143,7 @@ public: DumpFile(); virtual ~DumpFile(); - virtual bool open(const String &filename); + virtual bool open(const String &filename, bool createPath = false); virtual bool open(const FSNode &node); virtual void close(); |