280 lines
6.3 KiB
C++
280 lines
6.3 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2002-2003 The ScummVM project
|
|
*
|
|
* 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(__MORPHOS__)
|
|
|
|
#include <proto/dos.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "base/engine.h"
|
|
#include "../fs.h"
|
|
|
|
/*
|
|
* Implementation of the ScummVM file system API based on the MorphOS A-Box API.
|
|
*/
|
|
|
|
class ABoxFilesystemNode : public FilesystemNode {
|
|
protected:
|
|
BPTR _lock;
|
|
String _displayName;
|
|
bool _isDirectory;
|
|
bool _isValid;
|
|
String _path;
|
|
|
|
public:
|
|
ABoxFilesystemNode();
|
|
ABoxFilesystemNode(BPTR lock, CONST_STRPTR display_name = NULL);
|
|
ABoxFilesystemNode(const ABoxFilesystemNode *node);
|
|
~ABoxFilesystemNode();
|
|
|
|
virtual String displayName() const { return _displayName; }
|
|
virtual bool isValid() const { return _isValid; }
|
|
virtual bool isDirectory() const { return _isDirectory; }
|
|
virtual String path() const { return _path; }
|
|
|
|
virtual FSList *listDir(ListMode mode = kListDirectoriesOnly) const;
|
|
static FSList *listRoot();
|
|
virtual FilesystemNode *parent() const;
|
|
virtual FilesystemNode *clone() const { return new ABoxFilesystemNode(this); }
|
|
};
|
|
|
|
|
|
FilesystemNode *FilesystemNode::getRoot()
|
|
{
|
|
return new ABoxFilesystemNode();
|
|
}
|
|
|
|
ABoxFilesystemNode::ABoxFilesystemNode()
|
|
{
|
|
_displayName = "Mounted Volumes";
|
|
_isValid = true;
|
|
_isDirectory = true;
|
|
_path = "";
|
|
_lock = NULL;
|
|
}
|
|
|
|
ABoxFilesystemNode::ABoxFilesystemNode(BPTR lock, CONST_STRPTR display_name)
|
|
{
|
|
int bufsize = 256;
|
|
|
|
_lock = NULL;
|
|
for (;;)
|
|
{
|
|
char name[bufsize];
|
|
if (NameFromLock(lock, name, bufsize) != DOSFALSE)
|
|
{
|
|
_path = name;
|
|
_displayName = display_name ? display_name : FilePart(name);
|
|
break;
|
|
}
|
|
if (IoErr() != ERROR_LINE_TOO_LONG)
|
|
{
|
|
_isValid = false;
|
|
warning("Error while retrieving path name: %d", IoErr());
|
|
return;
|
|
}
|
|
bufsize *= 2;
|
|
}
|
|
|
|
_isValid = false;
|
|
|
|
FileInfoBlock *fib = (FileInfoBlock*) AllocDosObject(DOS_FIB, NULL);
|
|
if (fib == NULL)
|
|
{
|
|
warning("Failed to allocate memory for FileInfoBlock");
|
|
return;
|
|
}
|
|
|
|
if (Examine(lock, fib) != DOSFALSE)
|
|
{
|
|
_isDirectory = fib->fib_EntryType > 0;
|
|
if (_isDirectory)
|
|
{
|
|
if (fib->fib_EntryType != ST_ROOT)
|
|
_path += "/";
|
|
_lock = DupLock(lock);
|
|
_isValid = (_lock != NULL);
|
|
}
|
|
else
|
|
_isValid = true;
|
|
}
|
|
FreeDosObject(DOS_FIB, fib);
|
|
}
|
|
|
|
ABoxFilesystemNode::ABoxFilesystemNode(const ABoxFilesystemNode *node)
|
|
{
|
|
_displayName = node->_displayName;
|
|
_isValid = node->_isValid;
|
|
_isDirectory = node->_isDirectory;
|
|
_path = node->_path;
|
|
_lock = DupLock(node->_lock);
|
|
}
|
|
|
|
ABoxFilesystemNode::~ABoxFilesystemNode()
|
|
{
|
|
if (_lock)
|
|
{
|
|
UnLock(_lock);
|
|
_lock = NULL;
|
|
}
|
|
}
|
|
|
|
FSList *ABoxFilesystemNode::listDir(ListMode mode) const
|
|
{
|
|
FSList *myList = new FSList();
|
|
|
|
if (!_isValid)
|
|
error("listDir() called on invalid node");
|
|
|
|
if (!_isDirectory)
|
|
error("listDir() called on file node");
|
|
|
|
if (_lock == NULL)
|
|
{
|
|
/* This is the root node */
|
|
return listRoot();
|
|
}
|
|
|
|
/* "Normal" file system directory */
|
|
FileInfoBlock *fib = (FileInfoBlock*) AllocDosObject(DOS_FIB, NULL);
|
|
|
|
if (fib == NULL)
|
|
{
|
|
warning("Failed to allocate memory for FileInfoBlock");
|
|
return myList;
|
|
}
|
|
|
|
if (Examine(_lock, fib) != DOSFALSE)
|
|
{
|
|
while (ExNext(_lock, fib) != DOSFALSE)
|
|
{
|
|
ABoxFilesystemNode *entry;
|
|
String full_path;
|
|
BPTR lock;
|
|
|
|
if ((fib->fib_EntryType > 0 && (mode & kListDirectoriesOnly)) ||
|
|
(fib->fib_EntryType < 0 && (mode & kListFilesOnly)))
|
|
{
|
|
full_path = _path;
|
|
full_path += fib->fib_FileName;
|
|
lock = Lock(full_path.c_str(), SHARED_LOCK);
|
|
if (lock)
|
|
{
|
|
entry = new ABoxFilesystemNode(lock);
|
|
if (entry)
|
|
{
|
|
if (entry->isValid())
|
|
myList->push_back(*entry);
|
|
delete entry;
|
|
}
|
|
UnLock(lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IoErr() != ERROR_NO_MORE_ENTRIES)
|
|
warning("Error while reading directory: %d", IoErr());
|
|
}
|
|
|
|
FreeDosObject(DOS_FIB, fib);
|
|
|
|
return myList;
|
|
}
|
|
|
|
FilesystemNode *ABoxFilesystemNode::parent() const
|
|
{
|
|
FilesystemNode *node = NULL;
|
|
|
|
if (!_isDirectory)
|
|
error("parent() called on file node");
|
|
|
|
if (_lock == NULL)
|
|
/* Parent of the root is the root itself */
|
|
node = clone();
|
|
else
|
|
{
|
|
BPTR parent_lock = ParentDir(_lock);
|
|
if (parent_lock)
|
|
{
|
|
node = new ABoxFilesystemNode(parent_lock);
|
|
UnLock(parent_lock);
|
|
}
|
|
else
|
|
node = new ABoxFilesystemNode();
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
FSList *ABoxFilesystemNode::listRoot()
|
|
{
|
|
FSList *myList = new FSList();
|
|
DosList *dosList;
|
|
CONST ULONG lockDosListFlags = LDF_READ | LDF_VOLUMES;
|
|
char name[256];
|
|
|
|
dosList = LockDosList(lockDosListFlags);
|
|
if (dosList == NULL)
|
|
{
|
|
warning("Could not lock dos list");
|
|
return myList;
|
|
}
|
|
|
|
dosList = NextDosEntry(dosList, LDF_VOLUMES);
|
|
while (dosList)
|
|
{
|
|
if (dosList->dol_Type == DLT_VOLUME && // Should always be true, but ...
|
|
dosList->dol_Name && // Same here
|
|
dosList->dol_Task // Will be NULL if volume is removed from drive but still in use by some program
|
|
)
|
|
{
|
|
ABoxFilesystemNode *entry;
|
|
CONST_STRPTR volume_name = (CONST_STRPTR)BADDR(dosList->dol_Name)+1;
|
|
CONST_STRPTR device_name = (CONST_STRPTR)((struct Task *)dosList->dol_Task->mp_SigTask)->tc_Node.ln_Name;
|
|
BPTR volume_lock;
|
|
|
|
strcpy(name, volume_name);
|
|
strcat(name, ":");
|
|
volume_lock = Lock(name, SHARED_LOCK);
|
|
if (volume_lock)
|
|
{
|
|
sprintf(name, "%s (%s)", volume_name, device_name);
|
|
entry = new ABoxFilesystemNode(volume_lock, name);
|
|
if (entry)
|
|
{
|
|
if (entry->isValid())
|
|
myList->push_back(*entry);
|
|
delete entry;
|
|
}
|
|
UnLock(volume_lock);
|
|
}
|
|
}
|
|
dosList = NextDosEntry(dosList, LDF_VOLUMES);
|
|
}
|
|
|
|
UnLockDosList(lockDosListFlags);
|
|
|
|
return myList;
|
|
}
|
|
|
|
#endif // defined(__MORPHOS__)
|
|
|
|
|