ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

amigaos4-fs.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #if defined(__amigaos4__)
00024 
00025 #include "backends/fs/amigaos4/amigaos4-fs.h"
00026 #include "backends/fs/stdiostream.h"
00027 #include "common/debug.h"
00028 #include "common/util.h"
00029 
00030 #define ENTER() /* debug(6, "Enter") */
00031 #define LEAVE() /* debug(6, "Leave") */
00032 
00039 const char *lastPathComponent(const Common::String &str) {
00040     int offset = str.size();
00041 
00042     if (offset <= 0) {
00043         debug(6, "Bad offset");
00044         return 0;
00045     }
00046 
00047     const char *p = str.c_str();
00048 
00049     while (offset > 0 && (p[offset-1] == '/' || p[offset-1] == ':'))
00050         offset--;
00051 
00052     while (offset > 0 && (p[offset-1] != '/' && p[offset-1] != ':'))
00053         offset--;
00054 
00055     return p + offset;
00056 }
00057 
00058 AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
00059     ENTER();
00060     _sDisplayName = "Available Disks";
00061     _bIsValid = true;
00062     _bIsDirectory = true;
00063     _sPath = "";
00064     _pFileLock = 0;
00065     _nProt = 0; // Protection is ignored for the root volume
00066     LEAVE();
00067 }
00068 
00069 AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) {
00070     ENTER();
00071 
00072     int offset = p.size();
00073 
00074     //assert(offset > 0);
00075 
00076     if (offset <= 0) {
00077         debug(6, "Bad offset");
00078         return;
00079     }
00080 
00081     _sPath = p;
00082     _sDisplayName = ::lastPathComponent(_sPath);
00083     _pFileLock = 0;
00084     _bIsDirectory = false;
00085     _bIsValid = false;
00086 
00087     // Check whether the node exists and if it's a directory
00088     struct ExamineData * pExd = IDOS->ExamineObjectTags(EX_StringNameInput,_sPath.c_str(),TAG_END);
00089     if (pExd) {
00090         _nProt = pExd->Protection;
00091         if (EXD_IS_DIRECTORY(pExd)) {
00092             _bIsDirectory = true;
00093             _pFileLock = IDOS->Lock((CONST_STRPTR)_sPath.c_str(), SHARED_LOCK);
00094             _bIsValid = (_pFileLock != 0);
00095 
00096             // Add a trailing slash if needed
00097             const char c = _sPath.lastChar();
00098             if (c != '/' && c != ':')
00099                 _sPath += '/';
00100         } else {
00101             //_bIsDirectory = false;
00102             _bIsValid = true;
00103         }
00104 
00105         IDOS->FreeDosObject(DOS_EXAMINEDATA, pExd);
00106     }
00107 
00108     LEAVE();
00109 }
00110 
00111 AmigaOSFilesystemNode::AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName) {
00112     ENTER();
00113     int bufSize = MAXPATHLEN;
00114     _pFileLock = 0;
00115 
00116     while (true) {
00117         char *n = new char[bufSize];
00118         if (IDOS->NameFromLock(pLock, (STRPTR)n, bufSize) != DOSFALSE) {
00119             _sPath = n;
00120             _sDisplayName = pDisplayName ? pDisplayName : IDOS->FilePart((STRPTR)n);
00121             delete[] n;
00122             break;
00123         }
00124 
00125         if (IDOS->IoErr() != ERROR_LINE_TOO_LONG) {
00126             _bIsValid = false;
00127             debug(6, "IoErr() != ERROR_LINE_TOO_LONG");
00128             LEAVE();
00129             delete[] n;
00130             return;
00131         }
00132 
00133         bufSize *= 2;
00134         delete[] n;
00135     }
00136 
00137     _bIsValid = false;
00138     _bIsDirectory = false;
00139 
00140     struct ExamineData * pExd = IDOS->ExamineObjectTags(EX_FileLockInput,pLock,TAG_END);
00141     if (pExd) {
00142         _nProt = pExd->Protection;
00143         if (EXD_IS_DIRECTORY(pExd)) {
00144             _bIsDirectory = true;
00145             _pFileLock = IDOS->DupLock(pLock);
00146             _bIsValid = _pFileLock != 0;
00147 
00148             const char c = _sPath.lastChar();
00149             if (c != '/' && c != ':')
00150                 _sPath += '/';
00151         } else {
00152             //_bIsDirectory = false;
00153             _bIsValid = true;
00154         }
00155 
00156         IDOS->FreeDosObject(DOS_EXAMINEDATA, pExd);
00157     } else {
00158         debug(6, "ExamineObject() returned NULL");
00159     }
00160 
00161     LEAVE();
00162 }
00163 
00164 // We need the custom copy constructor because of DupLock()
00165 AmigaOSFilesystemNode::AmigaOSFilesystemNode(const AmigaOSFilesystemNode& node)
00166 : AbstractFSNode() {
00167     ENTER();
00168     _sDisplayName = node._sDisplayName;
00169     _bIsValid = node._bIsValid;
00170     _bIsDirectory = node._bIsDirectory;
00171     _sPath = node._sPath;
00172     _pFileLock = IDOS->DupLock(node._pFileLock);
00173     _nProt = node._nProt;
00174     LEAVE();
00175 }
00176 
00177 AmigaOSFilesystemNode::~AmigaOSFilesystemNode() {
00178     ENTER();
00179     if (_pFileLock)
00180         IDOS->UnLock(_pFileLock);
00181     LEAVE();
00182 }
00183 
00184 bool AmigaOSFilesystemNode::exists() const {
00185     ENTER();
00186     if (_sPath.empty())
00187         return false;
00188 
00189     bool nodeExists = false;
00190 
00191     // Previously we were trying to examine the node in order
00192     // to determine if the node exists or not.
00193     // I don't see the point : once you have been granted a
00194     // lock on it, it means it exists...
00195     //
00196     // =============================  Old code
00197     // BPTR pLock = IDOS->Lock((STRPTR)_sPath.c_str(), SHARED_LOCK);
00198     // if (pLock)
00199     // {
00200     //  if (IDOS->Examine(pLock, fib) != DOSFALSE)
00201     //      nodeExists = true;
00202     //  IDOS->UnLock(pLock);
00203     // }
00204     //
00205     // IDOS->FreeDosObject(DOS_FIB, fib);
00206     //
00207     // =============================  New code
00208     BPTR pLock = IDOS->Lock(_sPath.c_str(), SHARED_LOCK);
00209     if (pLock) {
00210         nodeExists = true;
00211         IDOS->UnLock(pLock);
00212     }
00213 
00214     LEAVE();
00215     return nodeExists;
00216 }
00217 
00218 AbstractFSNode *AmigaOSFilesystemNode::getChild(const Common::String &n) const {
00219     ENTER();
00220     if (!_bIsDirectory) {
00221         debug(6, "Not a directory");
00222         return 0;
00223     }
00224 
00225     Common::String newPath(_sPath);
00226 
00227     if (_sPath.lastChar() != '/')
00228         newPath += '/';
00229 
00230     newPath += n;
00231 
00232     LEAVE();
00233     return new AmigaOSFilesystemNode(newPath);
00234 }
00235 
00236 bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
00237     ENTER();
00238     bool ret = false;
00239 
00240     // TODO: Honor the hidden flag
00241     // There is no such thing as a hidden flag in AmigaOS...
00242 
00243     if (!_bIsValid) {
00244         debug(6, "Invalid node");
00245         LEAVE();
00246         return false; // Empty list
00247     }
00248 
00249     if (!_bIsDirectory) {
00250         debug(6, "Not a directory");
00251         LEAVE();
00252         return false; // Empty list
00253     }
00254 
00255     if (isRootNode()) {
00256         debug(6, "Root node");
00257         LEAVE();
00258         myList = listVolumes();
00259         return true;
00260     }
00261 
00262     APTR context = IDOS->ObtainDirContextTags(  EX_FileLockInput,   _pFileLock,
00263                                                 EX_DoCurrentDir,    TRUE,  /* for softlinks */
00264                                                 EX_DataFields,      (EXF_NAME|EXF_LINK|EXF_TYPE),
00265                                                 TAG_END);
00266     if (context) {
00267         struct ExamineData * pExd = NULL; // NB: No need to free the value after usage, everything will be dealt with by the DirContext release
00268 
00269         AmigaOSFilesystemNode *entry;
00270         while ( (pExd = IDOS->ExamineDir(context)) ) {
00271             if (     (EXD_IS_FILE(pExd) && ( Common::FSNode::kListFilesOnly == mode ))
00272                 ||  (EXD_IS_DIRECTORY(pExd) && ( Common::FSNode::kListDirectoriesOnly == mode ))
00273                 ||  Common::FSNode::kListAll == mode
00274                 )
00275             {
00276                 BPTR pLock = IDOS->Lock( pExd->Name, SHARED_LOCK );
00277                 if (pLock) {
00278                     entry = new AmigaOSFilesystemNode( pLock, pExd->Name );
00279                     if (entry) {
00280                         myList.push_back(entry);
00281                     }
00282 
00283                     IDOS->UnLock(pLock);
00284                 }
00285             }
00286         }
00287 
00288         if (ERROR_NO_MORE_ENTRIES != IDOS->IoErr() ) {
00289             debug(6, "An error occurred during ExamineDir");
00290             ret = false;
00291         } else {
00292             ret = true;
00293         }
00294 
00295 
00296         IDOS->ReleaseDirContext(context);
00297     } else {
00298         debug(6, "Unable to ObtainDirContext");
00299         ret = false;
00300     }
00301 
00302     LEAVE();
00303 
00304     return ret;
00305 }
00306 
00307 AbstractFSNode *AmigaOSFilesystemNode::getParent() const {
00308     ENTER();
00309 
00310     if (isRootNode()) {
00311         debug(6, "Root node");
00312         LEAVE();
00313         return new AmigaOSFilesystemNode(*this);
00314     }
00315 
00316     BPTR pLock = _pFileLock;
00317 
00318     if (!_bIsDirectory) {
00319         assert(!pLock);
00320         pLock = IDOS->Lock((CONST_STRPTR)_sPath.c_str(), SHARED_LOCK);
00321         assert(pLock);
00322     }
00323 
00324     AmigaOSFilesystemNode *node;
00325 
00326     BPTR parentDir = IDOS->ParentDir( pLock );
00327     if (parentDir) {
00328         node = new AmigaOSFilesystemNode(parentDir);
00329         IDOS->UnLock(parentDir);
00330     } else
00331         node = new AmigaOSFilesystemNode();
00332 
00333     if (!_bIsDirectory) {
00334         IDOS->UnLock(pLock);
00335     }
00336 
00337     LEAVE();
00338 
00339     return node;
00340 }
00341 
00342 bool AmigaOSFilesystemNode::isReadable() const {
00343     if (!_bIsValid)
00344         return false;
00345 
00346     // Regular RWED protection flags are low-active or inverted, thus the negation.
00347     // Moreover, a pseudo root filesystem is readable whatever the
00348     // protection says.
00349     bool readable = !(_nProt & EXDF_OTR_READ) || isRootNode();
00350 
00351     return readable;
00352 }
00353 
00354 bool AmigaOSFilesystemNode::isWritable() const {
00355     if (!_bIsValid)
00356         return false;
00357 
00358     // Regular RWED protection flags are low-active or inverted, thus the negation.
00359     // Moreover, a pseudo root filesystem is never writable whatever
00360     // the protection says (Because of it's pseudo nature).
00361     bool writable = !(_nProt & EXDF_OTR_WRITE) && !isRootNode();
00362 
00363     return writable;
00364 }
00365 
00366 AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
00367     ENTER();
00368 
00369     AbstractFSList myList;
00370 
00371     const uint32 kLockFlags = LDF_READ | LDF_VOLUMES;
00372     char buffer[MAXPATHLEN];
00373 
00374     struct DosList *dosList = IDOS->LockDosList(kLockFlags);
00375     if (!dosList) {
00376         debug(6, "Cannot lock the DOS list");
00377         LEAVE();
00378         return myList;
00379     }
00380 
00381     dosList = IDOS->NextDosEntry(dosList, LDF_VOLUMES);
00382     while (dosList) {
00383         if (dosList->dol_Type == DLT_VOLUME &&
00384             dosList->dol_Name &&
00385             dosList->dol_Port) {
00386 
00387             // The original line was
00388             //if (dosList->dol_Type == DLT_VOLUME &&
00389             //dosList->dol_Name &&
00390             //dosList->dol_Task) {
00391             // which errored using SDK 53.24 with a 'struct dosList' has no member called 'dol_Task'
00392             // The reason for that was that
00393             // 1) dol_Task wasn't a task pointer, it is a message port instead
00394             // 2) It was redefined to be dol_Port in dos/obsolete.h in afore mentioned SDK
00395 
00396             // Copy name to buffer
00397             IDOS->CopyStringBSTRToC(dosList->dol_Name, buffer, MAXPATHLEN);
00398 
00399             // Volume name + '\0'
00400             char *volName = new char [strlen(buffer) + 1];
00401 
00402             strcpy(volName, buffer);
00403 
00404             strcat(buffer, ":");
00405 
00406             BPTR volumeLock = IDOS->Lock((STRPTR)buffer, SHARED_LOCK);
00407             if (volumeLock) {
00408 
00409                 char *devName = new char [MAXPATHLEN];
00410 
00411                 // Find device name
00412                 IDOS->DevNameFromLock(volumeLock, devName, MAXPATHLEN, DN_DEVICEONLY);
00413 
00414                 sprintf(buffer, "%s (%s)", volName, devName);
00415 
00416                 delete[] devName;
00417 
00418                 AmigaOSFilesystemNode *entry = new AmigaOSFilesystemNode(volumeLock, buffer);
00419                 if (entry) {
00420                     myList.push_back(entry);
00421                 }
00422 
00423                 IDOS->UnLock(volumeLock);
00424             }
00425 
00426             delete[] volName;
00427         }
00428         dosList = IDOS->NextDosEntry(dosList, LDF_VOLUMES);
00429     }
00430 
00431     IDOS->UnLockDosList(kLockFlags);
00432 
00433     LEAVE();
00434 
00435     return myList;
00436 }
00437 
00438 Common::SeekableReadStream *AmigaOSFilesystemNode::createReadStream() {
00439     return StdioStream::makeFromPath(getPath(), false);
00440 }
00441 
00442 Common::WriteStream *AmigaOSFilesystemNode::createWriteStream() {
00443     return StdioStream::makeFromPath(getPath(), true);
00444 }
00445 
00446 bool AmigaOSFilesystemNode::create(bool isDirectoryFlag) {
00447     error("Not supported");
00448     return false;
00449 }
00450 
00451 #endif //defined(__amigaos4__)


Generated on Sat May 18 2019 05:00:54 for ResidualVM by doxygen 1.7.1
curved edge   curved edge