diff options
Diffstat (limited to 'backends/fs')
| -rw-r--r-- | backends/fs/morphos/abox-fs.cpp | 259 | 
1 files changed, 259 insertions, 0 deletions
diff --git a/backends/fs/morphos/abox-fs.cpp b/backends/fs/morphos/abox-fs.cpp new file mode 100644 index 0000000000..054c5d86b1 --- /dev/null +++ b/backends/fs/morphos/abox-fs.cpp @@ -0,0 +1,259 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002 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 "common/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() 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 = "All Drives"; +	_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) +		{ +			_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() 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; +			entry._displayName = fib->fib_FileName; +			entry._isDirectory = fib->fib_EntryType > 0; +			entry._path = _path; +			entry._path += fib->fib_FileName; +			if (entry._isDirectory) +				entry._path += "/"; +			myList->push_back(entry); +		} + +		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 = const_cast<ABoxFilesystemNode*>(this); +	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->isValid()) +					myList->push_back(*entry); +				UnLock(volume_lock); +			} +		} +		dosList = NextDosEntry(dosList, LDF_VOLUMES); +	} + +	UnLockDosList(lockDosListFlags); + +	return myList; +} + +#endif // defined(__MORPHOS__) +  | 
