DOSBox-X
|
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