DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/drive_iso.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <cctype>
00021 #include <cstring>
00022 #include "cdrom.h"
00023 #include "dosbox.h"
00024 #include "dos_system.h"
00025 #include "support.h"
00026 #include "drives.h"
00027 
00028 #define FLAGS1  ((iso) ? de.fileFlags : de.timeZone)
00029 #define FLAGS2  ((iso) ? de->fileFlags : de->timeZone)
00030 
00031 char fullname[LFN_NAMELENGTH];
00032 static Bit16u sdid[256];
00033 extern int lfn_filefind_handle;
00034 
00035 using namespace std;
00036 
00037 class isoFile : public DOS_File {
00038 public:
00039     isoFile(isoDrive* drive, const char* name, const FileStat_Block* stat, Bit32u offset);
00040         bool Read(Bit8u *data, Bit16u *size);
00041         bool Write(const Bit8u *data, Bit16u *size);
00042         bool Seek(Bit32u *pos, Bit32u type);
00043         bool Close();
00044         Bit16u GetInformation(void);
00045         Bit32u GetSeekPos(void);
00046 private:
00047         isoDrive *drive;
00048     Bit8u buffer[ISO_FRAMESIZE] = {};
00049     int cachedSector = -1;
00050         Bit32u fileBegin;
00051         Bit32u filePos;
00052         Bit32u fileEnd;
00053 //      Bit16u info;
00054 };
00055 
00056 isoFile::isoFile(isoDrive* drive, const char* name, const FileStat_Block* stat, Bit32u offset) : drive(drive), fileBegin(offset) {
00057         time = stat->time;
00058         date = stat->date;
00059         attr = stat->attr;
00060         filePos = fileBegin;
00061         fileEnd = fileBegin + stat->size;
00062         open = true;
00063         this->name = NULL;
00064         SetName(name);
00065 }
00066 
00067 bool isoFile::Read(Bit8u *data, Bit16u *size) {
00068         if (filePos + *size > fileEnd)
00069                 *size = (Bit16u)(fileEnd - filePos);
00070         
00071         Bit16u nowSize = 0;
00072         int sector = (int)(filePos / ISO_FRAMESIZE);
00073         Bit16u sectorPos = (Bit16u)(filePos % ISO_FRAMESIZE);
00074         
00075         if (sector != cachedSector) {
00076                 if (drive->readSector(buffer, (unsigned int)sector)) cachedSector = sector;
00077                 else { *size = 0; cachedSector = -1; }
00078         }
00079         while (nowSize < *size) {
00080                 Bit16u remSector = ISO_FRAMESIZE - sectorPos;
00081                 Bit16u remSize = *size - nowSize;
00082                 if(remSector < remSize) {
00083                         memcpy(&data[nowSize], &buffer[sectorPos], remSector);
00084                         nowSize += remSector;
00085                         sectorPos = 0;
00086                         sector++;
00087                         cachedSector++;
00088                         if (!drive->readSector(buffer, (unsigned int)sector)) {
00089                                 *size = nowSize;
00090                                 cachedSector = -1;
00091                         }
00092                 } else {
00093                         memcpy(&data[nowSize], &buffer[sectorPos], remSize);
00094                         nowSize += remSize;
00095                 }
00096                         
00097         }
00098         
00099         *size = nowSize;
00100         filePos += *size;
00101         return true;
00102 }
00103 
00104 bool isoFile::Write(const Bit8u* /*data*/, Bit16u* /*size*/) {
00105         return false;
00106 }
00107 
00108 bool isoFile::Seek(Bit32u *pos, Bit32u type) {
00109         switch (type) {
00110                 case DOS_SEEK_SET:
00111                         filePos = fileBegin + *pos;
00112                         break;
00113                 case DOS_SEEK_CUR:
00114                         filePos += *pos;
00115                         break;
00116                 case DOS_SEEK_END:
00117                         filePos = fileEnd + *pos;
00118                         break;
00119                 default:
00120                         return false;
00121         }
00122         if (filePos > fileEnd || filePos < fileBegin)
00123                 filePos = fileEnd;
00124         
00125         *pos = filePos - fileBegin;
00126         return true;
00127 }
00128 
00129 bool isoFile::Close() {
00130         if (refCtr == 1) open = false;
00131         return true;
00132 }
00133 
00134 Bit16u isoFile::GetInformation(void) {
00135         return 0x40;            // read-only drive
00136 }
00137 
00138 Bit32u isoFile::GetSeekPos() {
00139         return filePos - fileBegin;
00140 }
00141 
00142 
00143 int   MSCDEX_RemoveDrive(char driveLetter);
00144 int   MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit);
00145 void  MSCDEX_ReplaceDrive(CDROM_Interface* cdrom, Bit8u subUnit);
00146 bool  MSCDEX_HasDrive(char driveLetter);
00147 bool  MSCDEX_GetVolumeName(Bit8u subUnit, char* name);
00148 Bit8u MSCDEX_GetSubUnit(char driveLetter);
00149 
00150 bool CDROM_Interface_Image::images_init = false;
00151 
00152 isoDrive::isoDrive(char driveLetter, const char* fileName, Bit8u mediaid, int& error) {
00153 
00154     if (!CDROM_Interface_Image::images_init) {
00155         CDROM_Interface_Image::images_init = true;
00156         for (size_t i=0;i < 26;i++)
00157             CDROM_Interface_Image::images[i] = NULL;
00158     }
00159 
00160         this->fileName[0]  = '\0';
00161         this->discLabel[0] = '\0';
00162         subUnit = 0;
00163         nextFreeDirIterator = 0;
00164         memset(dirIterators, 0, sizeof(dirIterators));
00165         memset(sectorHashEntries, 0, sizeof(sectorHashEntries));
00166         memset(&rootEntry, 0, sizeof(isoDirEntry));
00167         
00168         safe_strncpy(this->fileName, fileName, CROSS_LEN);
00169         error = UpdateMscdex(driveLetter, fileName, subUnit);
00170 
00171         if (!error) {
00172                 if (loadImage()) {
00173                         strcpy(info, "isoDrive ");
00174                         strcat(info, fileName);
00175                         this->driveLetter = driveLetter;
00176                         this->mediaid = mediaid;
00177                         char buffer[32] = { 0 };
00178                         if (!MSCDEX_GetVolumeName(subUnit, buffer)) strcpy(buffer, "");
00179                         Set_Label(buffer,discLabel,true);
00180 
00181                 } else if (CDROM_Interface_Image::images[subUnit]->HasDataTrack() == false) { //Audio only cdrom
00182                         strcpy(info, "isoDrive ");
00183                         strcat(info, fileName);
00184                         this->driveLetter = driveLetter;
00185                         this->mediaid = mediaid;
00186                         char buffer[32] = { 0 };
00187                         strcpy(buffer, "Audio_CD");
00188                         Set_Label(buffer,discLabel,true);
00189                 } else error = 6; //Corrupt image
00190         }
00191 }
00192 
00193 isoDrive::~isoDrive() { }
00194 
00195 int isoDrive::UpdateMscdex(char driveLetter, const char* path, Bit8u& subUnit) {
00196         if (MSCDEX_HasDrive(driveLetter)) {
00197                 subUnit = MSCDEX_GetSubUnit(driveLetter);
00198                 CDROM_Interface_Image* oldCdrom = CDROM_Interface_Image::images[subUnit];
00199                 CDROM_Interface* cdrom = new CDROM_Interface_Image(subUnit);
00200                 char pathCopy[CROSS_LEN];
00201                 safe_strncpy(pathCopy, path, CROSS_LEN);
00202                 if (!cdrom->SetDevice(pathCopy, 0)) {
00203                         CDROM_Interface_Image::images[subUnit] = oldCdrom;
00204                         delete cdrom;
00205                         return 3;
00206                 }
00207                 MSCDEX_ReplaceDrive(cdrom, subUnit);
00208                 return 0;
00209         } else {
00210                 return MSCDEX_AddDrive(driveLetter, path, subUnit);
00211         }
00212 }
00213 
00214 void isoDrive::Activate(void) {
00215         UpdateMscdex(driveLetter, fileName, subUnit);
00216 }
00217 
00218 bool isoDrive::FileOpen(DOS_File **file, const char *name, Bit32u flags) {
00219         if ((flags & 0x0f) == OPEN_WRITE) {
00220                 DOS_SetError(DOSERR_ACCESS_DENIED);
00221                 return false;
00222         }
00223         
00224         isoDirEntry de;
00225         bool success = lookup(&de, name) && !IS_DIR(FLAGS1);
00226 
00227         if (success) {
00228                 FileStat_Block file_stat;
00229                 file_stat.size = DATA_LENGTH(de);
00230                 file_stat.attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY;
00231                 file_stat.date = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay);
00232                 file_stat.time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec);
00233                 *file = new isoFile(this, name, &file_stat, EXTENT_LOCATION(de) * ISO_FRAMESIZE);
00234                 (*file)->flags = flags;
00235         }
00236         return success;
00237 }
00238 
00239 bool isoDrive::FileCreate(DOS_File** /*file*/, const char* /*name*/, Bit16u /*attributes*/) {
00240         DOS_SetError(DOSERR_ACCESS_DENIED);
00241         return false;
00242 }
00243 
00244 bool isoDrive::FileUnlink(const char* /*name*/) {
00245         DOS_SetError(DOSERR_ACCESS_DENIED);
00246         return false;
00247 }
00248 
00249 bool isoDrive::RemoveDir(const char* /*dir*/) {
00250         DOS_SetError(DOSERR_ACCESS_DENIED);
00251         return false;
00252 }
00253 
00254 bool isoDrive::MakeDir(const char* /*dir*/) {
00255         DOS_SetError(DOSERR_ACCESS_DENIED);
00256         return false;
00257 }
00258 
00259 bool isoDrive::TestDir(const char *dir) {
00260         isoDirEntry de; 
00261         return (lookup(&de, dir) && IS_DIR(FLAGS1));
00262 }
00263 
00264 bool isoDrive::FindFirst(const char *dir, DOS_DTA &dta, bool fcb_findfirst) {
00265         isoDirEntry de;
00266         if (!lookup(&de, dir)) {
00267                 DOS_SetError(DOSERR_PATH_NOT_FOUND);
00268                 return false;
00269         }
00270         
00271         // get a directory iterator and save its id in the dta
00272         int dirIterator = GetDirIterator(&de);
00273         bool isRoot = (*dir == 0);
00274         dirIterators[dirIterator].root = isRoot;
00275         if (lfn_filefind_handle>=LFN_FILEFIND_MAX)
00276                 dta.SetDirID((Bit16u)dirIterator);
00277         else
00278                 sdid[lfn_filefind_handle]=dirIterator;
00279 
00280         Bit8u attr;
00281         char pattern[CROSS_LEN];
00282     dta.GetSearchParams(attr, pattern, uselfn);
00283    
00284         if (attr == DOS_ATTR_VOLUME) {
00285                 dta.SetResult(discLabel, discLabel, 0, 0, 0, DOS_ATTR_VOLUME);
00286                 return true;
00287         } else if ((attr & DOS_ATTR_VOLUME) && isRoot && !fcb_findfirst) {
00288                 if (WildFileCmp(discLabel,pattern)) {
00289                         // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir and if it matches the searchstring
00290                         dta.SetResult(discLabel, discLabel, 0, 0, 0, DOS_ATTR_VOLUME);
00291                         return true;
00292                 }
00293         }
00294 
00295         return FindNext(dta);
00296 }
00297 
00298 bool isoDrive::FindNext(DOS_DTA &dta) {
00299         Bit8u attr;
00300         char pattern[CROSS_LEN], findName[DOS_NAMELENGTH_ASCII], lfindName[ISO_MAXPATHNAME];
00301     dta.GetSearchParams(attr, pattern, uselfn);
00302         
00303         int dirIterator = lfn_filefind_handle>=LFN_FILEFIND_MAX?dta.GetDirID():sdid[lfn_filefind_handle];
00304         bool isRoot = dirIterators[dirIterator].root;
00305         
00306     isoDirEntry de = {};
00307         while (GetNextDirEntry(dirIterator, &de)) {
00308                 Bit8u findAttr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY;
00309                 if (IS_DIR(FLAGS1)) findAttr |= DOS_ATTR_DIRECTORY;
00310                 if (IS_HIDDEN(FLAGS1)) findAttr |= DOS_ATTR_HIDDEN;
00311 
00312                 if (strcmp((char*)de.ident,(char*)fullname))
00313                         strcpy(lfindName,fullname);
00314                 else
00315                         GetLongName((char*)de.ident,lfindName);
00316 
00317         if (!IS_ASSOC(FLAGS1) && !(isRoot && de.ident[0]=='.') && (WildFileCmp((char*)de.ident, pattern) || LWildFileCmp(lfindName, pattern))
00318                         && !(~attr & findAttr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM))) {
00319                         
00320                         /* file is okay, setup everything to be copied in DTA Block */
00321                         findName[0] = 0;
00322                         if(strlen((char*)de.ident) < DOS_NAMELENGTH_ASCII) {
00323                                 strcpy(findName, (char*)de.ident);
00324                                 upcase(findName);
00325                         }
00326                         Bit32u findSize = DATA_LENGTH(de);
00327                         Bit16u findDate = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay);
00328                         Bit16u findTime = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec);
00329             dta.SetResult(findName, lfindName, findSize, findDate, findTime, findAttr);
00330                         return true;
00331                 }
00332         }
00333         // after searching the directory, free the iterator
00334         FreeDirIterator(dirIterator);
00335         
00336         DOS_SetError(DOSERR_NO_MORE_FILES);
00337         return false;
00338 }
00339 
00340 bool isoDrive::Rename(const char* /*oldname*/, const char* /*newname*/) {
00341         DOS_SetError(DOSERR_ACCESS_DENIED);
00342         return false;
00343 }
00344 
00345 bool isoDrive::SetFileAttr(const char * name,Bit16u attr) {
00346     (void)name;
00347     (void)attr;
00348         return false;
00349 }
00350 
00351 bool isoDrive::GetFileAttr(const char *name, Bit16u *attr) {
00352         *attr = 0;
00353         isoDirEntry de;
00354         bool success = lookup(&de, name);
00355         if (success) {
00356                 *attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY;
00357                 if (IS_HIDDEN(FLAGS1)) *attr |= DOS_ATTR_HIDDEN;
00358                 if (IS_DIR(FLAGS1)) *attr |= DOS_ATTR_DIRECTORY;
00359         }
00360         return success;
00361 }
00362 
00363 bool isoDrive::GetFileAttrEx(char* name, struct stat *status) {
00364     (void)name;
00365     (void)status;
00366         return false;
00367 }
00368 
00369 unsigned long isoDrive::GetCompressedSize(char* name) {
00370     (void)name;
00371         return 0;
00372 }
00373 
00374 #if defined (WIN32)
00375 HANDLE isoDrive::CreateOpenFile(const char* name) {
00376     (void)name;
00377         DOS_SetError(1);
00378         return INVALID_HANDLE_VALUE;
00379 }
00380 #endif
00381 
00382 bool isoDrive::AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters) {
00383         *bytes_sector = 2048;
00384         *sectors_cluster = 1; // cluster size for cdroms ?
00385         *total_clusters = 65535;
00386         *free_clusters = 0;
00387         return true;
00388 }
00389 
00390 bool isoDrive::FileExists(const char *name) {
00391         isoDirEntry de;
00392         return (lookup(&de, name) && !IS_DIR(FLAGS1));
00393 }
00394 
00395 bool isoDrive::FileStat(const char *name, FileStat_Block *const stat_block) {
00396         isoDirEntry de;
00397         bool success = lookup(&de, name);
00398         
00399         if (success) {
00400                 stat_block->date = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay);
00401                 stat_block->time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec);
00402                 stat_block->size = DATA_LENGTH(de);
00403                 stat_block->attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY;
00404                 if (IS_DIR(FLAGS1)) stat_block->attr |= DOS_ATTR_DIRECTORY;
00405         }
00406         
00407         return success;
00408 }
00409 
00410 Bit8u isoDrive::GetMediaByte(void) {
00411         return mediaid;
00412 }
00413 
00414 bool isoDrive::isRemote(void) {
00415         return true;
00416 }
00417 
00418 bool isoDrive::isRemovable(void) {
00419         return true;
00420 }
00421 
00422 Bits isoDrive::UnMount(void) {
00423         if(MSCDEX_RemoveDrive(driveLetter)) {
00424                 delete this;
00425                 return 0;
00426         }
00427         return 2;
00428 }
00429 
00430 int isoDrive::GetDirIterator(const isoDirEntry* de) {
00431         int dirIterator = nextFreeDirIterator;
00432         
00433         // get start and end sector of the directory entry (pad end sector if necessary)
00434         dirIterators[dirIterator].currentSector = EXTENT_LOCATION(*de);
00435         dirIterators[dirIterator].endSector =
00436                 EXTENT_LOCATION(*de) + DATA_LENGTH(*de) / ISO_FRAMESIZE - 1;
00437         if (DATA_LENGTH(*de) % ISO_FRAMESIZE != 0)
00438                 dirIterators[dirIterator].endSector++;
00439         
00440         // reset position and mark as valid
00441         dirIterators[dirIterator].pos = 0;
00442         dirIterators[dirIterator].valid = true;
00443 
00444         // advance to next directory iterator (wrap around if necessary)
00445         nextFreeDirIterator = (nextFreeDirIterator + 1) % MAX_OPENDIRS;
00446         
00447         return dirIterator;
00448 }
00449 
00450 bool isoDrive::GetNextDirEntry(const int dirIteratorHandle, isoDirEntry* de) {
00451         bool result = false;
00452         Bit8u* buffer = NULL;
00453         DirIterator& dirIterator = dirIterators[dirIteratorHandle];
00454         
00455         // check if the directory entry is valid
00456         if (dirIterator.valid && ReadCachedSector(&buffer, dirIterator.currentSector)) {
00457                 // check if the next sector has to be read
00458                 if ((dirIterator.pos >= ISO_FRAMESIZE)
00459                  || (buffer[dirIterator.pos] == 0)
00460                  || (dirIterator.pos + buffer[dirIterator.pos] > ISO_FRAMESIZE)) {
00461                         
00462                         // check if there is another sector available
00463                         if (dirIterator.currentSector < dirIterator.endSector) {
00464                                 dirIterator.pos = 0;
00465                                 dirIterator.currentSector++;
00466                                 if (!ReadCachedSector(&buffer, dirIterator.currentSector)) {
00467                                         return false;
00468                                 }
00469                         } else {
00470                                 return false;
00471                         }
00472                  }
00473                  // read sector and advance sector pointer
00474                  int length = readDirEntry(de, &buffer[dirIterator.pos]);
00475                  result = length >= 0;
00476          if (length > 0) dirIterator.pos += (unsigned int)length;
00477         }
00478         return result;
00479 }
00480 
00481 void isoDrive::FreeDirIterator(const int dirIterator) {
00482         dirIterators[dirIterator].valid = false;
00483         
00484         // if this was the last aquired iterator decrement nextFreeIterator
00485         if ((dirIterator + 1) % MAX_OPENDIRS == nextFreeDirIterator) {
00486                 if (nextFreeDirIterator>0) {
00487                         nextFreeDirIterator--;
00488                 } else {
00489                         nextFreeDirIterator = MAX_OPENDIRS-1;
00490                 }
00491         }
00492 }
00493 
00494 bool isoDrive::ReadCachedSector(Bit8u** buffer, const Bit32u sector) {
00495         // get hash table entry
00496         unsigned int pos = sector % ISO_MAX_HASH_TABLE_SIZE;
00497         SectorHashEntry& he = sectorHashEntries[pos];
00498         
00499         // check if the entry is valid and contains the correct sector
00500         if (!he.valid || he.sector != sector) {
00501                 if (!CDROM_Interface_Image::images[subUnit]->ReadSector(he.data, false, sector)) {
00502                         return false;
00503                 }
00504                 he.valid = true;
00505                 he.sector = sector;
00506         }
00507         
00508         *buffer = he.data;
00509         return true;
00510 }
00511 
00512 inline bool isoDrive :: readSector(Bit8u *buffer, Bit32u sector) {
00513         return CDROM_Interface_Image::images[subUnit]->ReadSector(buffer, false, sector);
00514 }
00515 
00516 int isoDrive::readDirEntry(isoDirEntry* de, const Bit8u* data) {
00517         // copy data into isoDirEntry struct, data[0] = length of DirEntry
00518 //      if (data[0] > sizeof(isoDirEntry)) return -1;//check disabled as isoDirentry is currently 258 bytes large. So it always fits
00519         memcpy(de, data, data[0]);//Perharps care about a zero at the end.
00520         
00521         // xa not supported
00522         if (de->extAttrLength != 0) return -1;
00523         // interleaved mode not supported
00524         if (de->fileUnitSize != 0 || de->interleaveGapSize != 0) return -1;
00525         
00526         // modify file identifier for use with dosbox
00527         if (de->length < 33 + de->fileIdentLength) return -1;
00528         if (IS_DIR(FLAGS2)) {
00529                 if (de->fileIdentLength == 1 && de->ident[0] == 0) strcpy((char*)de->ident, ".");
00530                 else if (de->fileIdentLength == 1 && de->ident[0] == 1) strcpy((char*)de->ident, "..");
00531                 else {
00532                         if (de->fileIdentLength > 200) return -1;
00533                         de->ident[de->fileIdentLength] = 0;
00534                 }
00535         } else {
00536                 if (de->fileIdentLength > 200) return -1;
00537                 de->ident[de->fileIdentLength] = 0;     
00538                 // remove any file version identifiers as there are some cdroms that don't have them
00539                 strreplace((char*)de->ident, ';', 0);   
00540                 // if file has no extension remove the trailing dot
00541                 size_t tmp = strlen((char*)de->ident);
00542                 if (tmp > 0) {
00543                         if (de->ident[tmp - 1] == '.') de->ident[tmp - 1] = 0;
00544                 }
00545         }
00546         strcpy((char*)fullname,(char*)de->ident);
00547         char* dotpos = strchr((char*)de->ident, '.');
00548         if (dotpos!=NULL) {
00549                 if (strlen(dotpos)>4) dotpos[4]=0;
00550                 if (dotpos-(char*)de->ident>8) {
00551                         strcpy((char*)(&de->ident[8]),dotpos);
00552                 }
00553         } else if (strlen((char*)de->ident)>8) de->ident[8]=0;
00554         return de->length;
00555 }
00556 
00557 bool isoDrive :: loadImage() {
00558         Bit8u pvd[COOKED_SECTOR_SIZE];
00559         dataCD = false;
00560         readSector(pvd, ISO_FIRST_VD);
00561         if (pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) iso = true;
00562         else if (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1) iso = false;
00563         else return false;
00564         Bit16u offset = iso ? 156 : 180;
00565         if (readDirEntry(&this->rootEntry, &pvd[offset])>0) {
00566                 dataCD = true;
00567                 return true;
00568         }
00569         return false;
00570 }
00571 
00572 bool isoDrive :: lookup(isoDirEntry *de, const char *path) {
00573         if (!dataCD) return false;
00574         *de = this->rootEntry;
00575         if (!strcmp(path, "")) return true;
00576         
00577         char isoPath[ISO_MAXPATHNAME], longname[ISO_MAXPATHNAME];
00578         safe_strncpy(isoPath, path, ISO_MAXPATHNAME);
00579         strreplace(isoPath, '\\', '/');
00580         
00581         // iterate over all path elements (name), and search each of them in the current de
00582         for(char* name = strtok(isoPath, "/"); NULL != name; name = strtok(NULL, "/")) {
00583 
00584                 bool found = false;     
00585                 // current entry must be a directory, abort otherwise
00586                 if (IS_DIR(FLAGS2)) {
00587                         
00588                         // remove the trailing dot if present
00589                         size_t nameLength = strlen(name);
00590                         if (nameLength > 0) {
00591                                 if (name[nameLength - 1] == '.') name[nameLength - 1] = 0;
00592                         }
00593                         
00594                         // look for the current path element
00595                         int dirIterator = GetDirIterator(de);
00596                         while (!found && GetNextDirEntry(dirIterator, de)) {
00597                                 GetLongName((char*)de->ident,longname);
00598                                 if (!IS_ASSOC(FLAGS2) && ((0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH)) || 0 == strncasecmp((char*) longname, name, ISO_MAXPATHNAME))) {
00599                                         found = true;
00600                                 }
00601                         }
00602                         FreeDirIterator(dirIterator);
00603                 }
00604                 if (!found) return false;
00605         }
00606         return true;
00607 }
00608 
00609 void IDE_ATAPI_MediaChangeNotify(unsigned char drive_index);
00610 
00611 void isoDrive :: MediaChange() {
00612         IDE_ATAPI_MediaChangeNotify(toupper(driveLetter) - 'A'); /* ewwww */
00613 }
00614 
00615 void isoDrive::GetLongName(const char* ident, char* lfindName) {
00616     const char* c = ident + strlen(ident);
00617     int i,j=(int)(222-strlen(ident)-6);
00618     for (i=5;i<j;i++) {
00619         if (*(c+i)=='N'&&*(c+i+1)=='M'&&*(c+i+2)>0&&*(c+i+3)==1&&*(c+i+4)==0&&*(c+i+5)>0)
00620             break;
00621         }
00622     if (i<j&&strcmp(ident,".")&&strcmp(ident,"..")) {
00623         strncpy(lfindName,c+i+5,*(c+i+2)-5);
00624         lfindName[*(c+i+2)-5]=0;
00625     } else
00626         strcpy(lfindName,ident);
00627 }
00628 
00629