aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/fs/amigaos4/.cvsignore1
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp377
2 files changed, 378 insertions, 0 deletions
diff --git a/backends/fs/amigaos4/.cvsignore b/backends/fs/amigaos4/.cvsignore
new file mode 100644
index 0000000000..39a06683b7
--- /dev/null
+++ b/backends/fs/amigaos4/.cvsignore
@@ -0,0 +1 @@
+.deps
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
new file mode 100644
index 0000000000..1726f82b31
--- /dev/null
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -0,0 +1,377 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005 The ScummVM project, contribution by Hans-Jörg Frieden and Juha Niemimäki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#if defined(__amigaos4__)
+#ifdef __USE_INLINE__
+#undef __USE_INLINE__
+#endif
+
+#include <proto/exec.h>
+#include <proto/dos.h>
+#include <stdio.h>
+
+#ifndef USE_NEWLIB
+#include <strings.h>
+#endif
+
+#include <stdafx.h>
+
+#include "util.h"
+
+#include "base/engine.h"
+#include "../fs.h"
+
+#define ENTER() /* debug(6, "Enter\n") */
+#define LEAVE() /* debug(6, "Leave\n") */
+
+
+const uint32 ExAllBufferSize = 40960;
+
+class AmigaOSFilesystemNode : public AbstractFilesystemNode {
+ protected:
+ BPTR _pFileLock;
+ String _sDisplayName;
+ bool _bIsDirectory;
+ bool _bIsValid;
+ String _sPath;
+
+ public:
+ AmigaOSFilesystemNode();
+ AmigaOSFilesystemNode(const AmigaOSFilesystemNode *pNode);
+ AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0);
+ AmigaOSFilesystemNode(const String &p);
+
+ ~AmigaOSFilesystemNode();
+
+ virtual String displayName() const { return _sDisplayName; };
+ virtual bool isValid() const { return _bIsValid; };
+ virtual bool isDirectory() const { return _bIsDirectory; };
+ virtual String path() const { return _sPath; };
+
+ virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const;
+ virtual FSList listVolumes(void) const;
+ virtual AbstractFilesystemNode *parent() const;
+ virtual AbstractFilesystemNode *clone() const { return new AmigaOSFilesystemNode(this); };
+};
+
+AbstractFilesystemNode *FilesystemNode::getRoot() {
+ return new AmigaOSFilesystemNode();
+}
+
+AbstractFilesystemNode *FilesystemNode::getNodeForPath(const String &path) {
+ return new AmigaOSFilesystemNode(path);
+}
+
+AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
+ ENTER();
+ _sDisplayName = "Available Disks";
+ _bIsValid = true;
+ _bIsDirectory = true;
+ _sPath = "";
+ _pFileLock = 0;
+ LEAVE();
+}
+
+
+AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
+ ENTER();
+
+ int len = 0, offset = p.size();
+
+ assert(offset > 0);
+
+ _sPath = p;
+
+ // Extract last component from path
+ const char *str = p.c_str();
+
+ while (offset > 0 && (str[offset-1] == '/' || str[offset-1] == ':'))
+ offset--;
+
+ while (offset > 0 && (str[offset-1] != '/' && str[offset-1] != ':')) {
+ len++;
+ offset--;
+ }
+
+ _sDisplayName = String(str + offset, len);
+
+ // Check whether it is a directory, and whether the file actually exists
+
+ struct FileInfoBlock *fib = (struct FileInfoBlock *)IDOS->AllocDosObject(DOS_FIB, NULL);
+ if (!fib) {
+ debug(6, "fib == 0\n");
+ LEAVE();
+ return;
+ }
+
+ BPTR pLock = IDOS->Lock( (char *)_sPath.c_str(), SHARED_LOCK);
+ if (pLock) {
+ if (IDOS->Examine(pLock, fib) != DOSFALSE) {
+ if (fib->fib_EntryType > 0)
+ _bIsDirectory = true;
+ else
+ _bIsDirectory = false;
+
+ if (_bIsDirectory) {
+ if (fib->fib_EntryType != ST_ROOT)
+ _sPath += "/";
+
+ _pFileLock = IDOS->DupLock(pLock);
+ _bIsValid = (_pFileLock != 0);
+ }
+ else _bIsValid = true;
+ }
+ }
+
+ IDOS->FreeDosObject(DOS_FIB, fib);
+ LEAVE();
+}
+
+AmigaOSFilesystemNode::AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName) {
+ ENTER();
+ int bufsize = 256;
+ _pFileLock = 0;
+
+ while (1) {
+ char *name = new char[bufsize];
+ if (IDOS->NameFromLock(pLock, name, bufsize) != DOSFALSE) {
+ _sPath = name;
+ _sDisplayName = pDisplayName ? pDisplayName : IDOS->FilePart(name);
+ delete name;
+ break;
+ }
+
+ if (IDOS->IoErr() != ERROR_LINE_TOO_LONG) {
+ _bIsValid = false;
+ debug(6, "Error\n");
+ LEAVE();
+ delete name;
+ return;
+ }
+ bufsize *= 2;
+ delete name;
+ }
+
+ _bIsValid = false;
+
+ struct FileInfoBlock *fib = (struct FileInfoBlock *)IDOS->AllocDosObject(DOS_FIB, NULL);
+ if (!fib) {
+ debug(6, "fib == 0\n");
+ LEAVE();
+ return;
+ }
+
+ if (IDOS->Examine(pLock, fib) != DOSFALSE) {
+ if (fib->fib_EntryType > 0)
+ _bIsDirectory = true;
+ else
+ _bIsDirectory = false;
+
+ if (_bIsDirectory) {
+ if (fib->fib_EntryType != ST_ROOT)
+ _sPath += "/";
+
+ _pFileLock = IDOS->DupLock(pLock);
+ _bIsValid = (_pFileLock != 0);
+ }
+ else _bIsValid = true;
+ }
+
+ IDOS->FreeDosObject(DOS_FIB, fib);
+ LEAVE();
+}
+
+AmigaOSFilesystemNode::AmigaOSFilesystemNode(const AmigaOSFilesystemNode *node) {
+ ENTER();
+ _sDisplayName = node->_sDisplayName;
+ _bIsValid = node->_bIsValid;
+ _bIsDirectory = node->_bIsDirectory;
+ _sPath = node->_sPath;
+ _pFileLock = IDOS->DupLock(node->_pFileLock);
+ LEAVE();
+}
+
+AmigaOSFilesystemNode::~AmigaOSFilesystemNode() {
+ ENTER();
+ if (_pFileLock)
+ IDOS->UnLock(_pFileLock);
+ LEAVE();
+}
+
+FSList AmigaOSFilesystemNode::listDir(ListMode mode) const {
+ ENTER();
+
+ if (!_bIsValid) {
+ debug(6, "Invalid node\n");
+ LEAVE();
+ //return 0;
+ }
+
+ if (!_bIsDirectory) {
+ debug(6, "Not a directory\n");
+ LEAVE();
+ //return 0;
+ }
+
+ if (_pFileLock == 0) {
+ debug(6, "Root node\n");
+ LEAVE();
+ return listVolumes();
+ }
+
+ //FSList *myList = new FSList();
+ FSList myList;
+
+ struct ExAllControl *eac;
+ struct ExAllData *data, *ead;
+ BOOL bExMore;
+
+ eac = (struct ExAllControl *)IDOS->AllocDosObject(DOS_EXALLCONTROL, 0);
+ if (eac) {
+ data = (struct ExAllData *)IExec->AllocVec(ExAllBufferSize, MEMF_ANY);
+ if (data) {
+ eac->eac_LastKey = 0;
+ do {
+ bExMore = IDOS->ExAll(_pFileLock, data, ExAllBufferSize,
+ ED_TYPE, eac);
+
+ LONG error = IDOS->IoErr();
+ if (!bExMore && error != ERROR_NO_MORE_ENTRIES)
+ break;
+
+ if (eac->eac_Entries == 0)
+ continue;
+
+ ead = data;
+ do {
+ AmigaOSFilesystemNode *entry;
+ String full_path;
+ BPTR lock;
+
+ if ((ead->ed_Type > 0 && (mode & kListDirectoriesOnly)) ||
+ (ead->ed_Type < 0 && (mode & kListFilesOnly))) {
+ full_path = _sPath;
+ full_path += (char*)ead->ed_Name;
+ lock = IDOS->Lock((char *)full_path.c_str(), SHARED_LOCK);
+ if (lock) {
+ entry = new AmigaOSFilesystemNode(lock, (char *)ead->ed_Name);
+ if (entry) {
+ if (entry->isValid())
+ myList.push_back(wrap(entry));
+ else
+ delete entry;
+ }
+ IDOS->UnLock(lock);
+ }
+ }
+ ead = ead->ed_Next;
+ } while (ead);
+ } while (bExMore);
+
+ IExec->FreeVec(data);
+ }
+
+ IDOS->FreeDosObject(DOS_EXALLCONTROL, eac);
+ }
+ LEAVE();
+ return myList;
+}
+
+AbstractFilesystemNode *AmigaOSFilesystemNode::parent() const {
+ ENTER();
+ AmigaOSFilesystemNode *node;
+
+ if (!_bIsDirectory) {
+ debug(6, "No directory\n");
+ LEAVE();
+ return 0;
+ }
+
+ if (_pFileLock == 0) {
+ debug(6, "Root node\n");
+ LEAVE();
+ return clone();
+ }
+
+ BPTR parent = IDOS->ParentDir(_pFileLock);
+ if (parent) {
+ node = new AmigaOSFilesystemNode(parent);
+ IDOS->UnLock(parent);
+ }
+ else
+ node = new AmigaOSFilesystemNode();
+
+ LEAVE();
+ return node;
+}
+
+FSList AmigaOSFilesystemNode::listVolumes(void) const {
+ ENTER();
+ //FSList *myList = new FSList();
+ FSList myList;
+
+ struct DosList *dosList;
+
+ const uint32 lockFlags = LDF_READ | LDF_VOLUMES;
+ char name[256];
+
+ dosList = IDOS->LockDosList(lockFlags);
+ if (!dosList) {
+ debug(6, "Cannot lock dos list\n");
+ LEAVE();
+ return myList;
+ }
+
+
+ dosList = IDOS->NextDosEntry(dosList, LDF_VOLUMES);
+ while (dosList) {
+ if (dosList->dol_Type == DLT_VOLUME &&
+ dosList->dol_Name &&
+ dosList->dol_Task) {
+ AmigaOSFilesystemNode *entry;
+ const char *volname = (const char *)BADDR(dosList->dol_Name)+1;
+ const char *devname = (const char *)((struct Task *)dosList->dol_Task->mp_SigTask)->tc_Node.ln_Name;
+
+ strcpy(name, volname);
+ strcat(name, ":");
+
+ BPTR volume_lock = IDOS->Lock(name, SHARED_LOCK);
+ if (volume_lock) {
+ sprintf(name, "%s (%s)", volname, devname);
+ entry = new AmigaOSFilesystemNode(volume_lock, name);
+ if (entry) {
+ if (entry->isValid())
+ myList.push_back(wrap(entry));
+ else
+ delete entry;
+ }
+ IDOS->UnLock(volume_lock);
+ }
+ }
+ dosList = IDOS->NextDosEntry(dosList, LDF_VOLUMES);
+ }
+
+ IDOS->UnLockDosList(lockFlags);
+
+ LEAVE();
+ return myList;
+}
+
+#endif