1 /* 2 * Copyright (C) 2002-2021 The DOSBox Team 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #ifndef DOSBOX_DRIVES_H 20 #define DOSBOX_DRIVES_H 21 22 #include "dosbox.h" 23 24 #include <memory> 25 #include <unordered_set> 26 #include <string> 27 #include <vector> 28 29 #include "dos_inc.h" 30 #include "dos_system.h" 31 32 bool WildFileCmp(const char * file, const char * wild); 33 void Set_Label(char const * const input, char * const output, bool cdrom); 34 std::string To_Label(const char* name); 35 36 class DriveManager { 37 public: 38 static void AppendDisk(int drive, DOS_Drive* disk); 39 static void InitializeDrive(int drive); 40 static int UnmountDrive(int drive); 41 // static void CycleDrive(bool pressed); 42 // static void CycleDisk(bool pressed); 43 static void CycleDisks(int drive, bool notify); 44 static void CycleAllDisks(void); 45 static void Init(Section* sec); 46 47 private: 48 static struct DriveInfo { 49 std::vector<DOS_Drive*> disks = {}; 50 int currentDisk = 0; 51 } driveInfos[DOS_DRIVES]; 52 53 static int currentDrive; 54 }; 55 56 class localDrive : public DOS_Drive { 57 public: 58 localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid); 59 virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); 60 virtual FILE *GetSystemFilePtr(char const * const name, char const * const type); 61 virtual bool GetSystemFilename(char* sysName, char const * const dosName); 62 virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); 63 virtual bool FileUnlink(char * name); 64 virtual bool RemoveDir(char * dir); 65 virtual bool MakeDir(char * dir); 66 virtual bool TestDir(char * dir); 67 virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); 68 virtual bool FindNext(DOS_DTA & dta); 69 virtual bool GetFileAttr(char * name,Bit16u * attr); 70 virtual bool Rename(char * oldname,char * newname); 71 virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); 72 virtual bool FileExists(const char* name); 73 virtual bool FileStat(const char* name, FileStat_Block * const stat_block); 74 virtual Bit8u GetMediaByte(void); 75 virtual bool isRemote(void); 76 virtual bool isRemovable(void); 77 virtual Bits UnMount(void); GetBasedir()78 const char *GetBasedir() const { return basedir; } 79 80 protected: 81 char basedir[CROSS_LEN] = ""; 82 struct { 83 char srch_dir[CROSS_LEN] = ""; 84 } srchInfo[MAX_OPENDIRS]; 85 86 private: 87 bool IsFirstEncounter(const std::string& filename); 88 std::unordered_set<std::string> write_protected_files; 89 struct { 90 Bit16u bytes_sector; 91 Bit8u sectors_cluster; 92 Bit16u total_clusters; 93 Bit16u free_clusters; 94 Bit8u mediaid; 95 } allocation; 96 }; 97 98 #ifdef _MSC_VER 99 #pragma pack (1) 100 #endif 101 struct bootstrap { 102 Bit8u nearjmp[3]; 103 Bit8u oemname[8]; 104 Bit16u bytespersector; 105 Bit8u sectorspercluster; 106 Bit16u reservedsectors; 107 Bit8u fatcopies; 108 Bit16u rootdirentries; 109 Bit16u totalsectorcount; 110 Bit8u mediadescriptor; 111 Bit16u sectorsperfat; 112 Bit16u sectorspertrack; 113 Bit16u headcount; 114 /* 32-bit FAT extensions */ 115 Bit32u hiddensectorcount; 116 Bit32u totalsecdword; 117 Bit8u bootcode[474]; 118 Bit8u magic1; /* 0x55 */ 119 Bit8u magic2; /* 0xaa */ 120 } GCC_ATTRIBUTE(packed); 121 122 struct direntry { 123 Bit8u entryname[11]; 124 Bit8u attrib; 125 Bit8u NTRes; 126 Bit8u milliSecondStamp; 127 Bit16u crtTime; 128 Bit16u crtDate; 129 Bit16u accessDate; 130 Bit16u hiFirstClust; 131 Bit16u modTime; 132 Bit16u modDate; 133 Bit16u loFirstClust; 134 Bit32u entrysize; 135 } GCC_ATTRIBUTE(packed); 136 137 struct partTable { 138 Bit8u booter[446]; 139 struct { 140 Bit8u bootflag; 141 Bit8u beginchs[3]; 142 Bit8u parttype; 143 Bit8u endchs[3]; 144 Bit32u absSectStart; 145 Bit32u partSize; 146 } pentry[4]; 147 Bit8u magic1; /* 0x55 */ 148 Bit8u magic2; /* 0xaa */ 149 } GCC_ATTRIBUTE(packed); 150 151 #ifdef _MSC_VER 152 #pragma pack () 153 #endif 154 //Forward 155 class imageDisk; 156 class fatDrive final : public DOS_Drive { 157 public: 158 fatDrive(const char * sysFilename, Bit32u bytesector, Bit32u cylsector, Bit32u headscyl, Bit32u cylinders, Bit32u startSector); 159 fatDrive(const fatDrive&) = delete; // prevent copying 160 fatDrive& operator= (const fatDrive&) = delete; // prevent assignment 161 virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); 162 virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); 163 virtual bool FileUnlink(char * name); 164 virtual bool RemoveDir(char * dir); 165 virtual bool MakeDir(char * dir); 166 virtual bool TestDir(char * dir); 167 virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); 168 virtual bool FindNext(DOS_DTA & dta); 169 virtual bool GetFileAttr(char * name,Bit16u * attr); 170 virtual bool Rename(char * oldname,char * newname); 171 virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); 172 virtual bool FileExists(const char* name); 173 virtual bool FileStat(const char* name, FileStat_Block * const stat_block); 174 virtual Bit8u GetMediaByte(void); 175 virtual bool isRemote(void); 176 virtual bool isRemovable(void); 177 virtual Bits UnMount(void); EmptyCache(void)178 virtual void EmptyCache(void){} 179 public: 180 Bit8u readSector(Bit32u sectnum, void * data); 181 Bit8u writeSector(Bit32u sectnum, void * data); 182 Bit32u getAbsoluteSectFromBytePos(Bit32u startClustNum, Bit32u bytePos); 183 Bit32u getSectorSize(void); 184 Bit32u getClusterSize(void); 185 Bit32u getAbsoluteSectFromChain(Bit32u startClustNum, Bit32u logicalSector); 186 bool allocateCluster(Bit32u useCluster, Bit32u prevCluster); 187 Bit32u appendCluster(Bit32u startCluster); 188 void deleteClustChain(Bit32u startCluster, Bit32u bytePos); 189 Bit32u getFirstFreeClust(void); 190 bool directoryBrowse(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum, Bit32s start=0); 191 bool directoryChange(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum); 192 std::shared_ptr<imageDisk> loadedDisk; 193 bool created_successfully; 194 private: 195 Bit32u getClusterValue(Bit32u clustNum); 196 void setClusterValue(Bit32u clustNum, Bit32u clustValue); 197 Bit32u getClustFirstSect(Bit32u clustNum); 198 bool FindNextInternal(Bit32u dirClustNumber, DOS_DTA & dta, direntry *foundEntry); 199 bool getDirClustNum(char * dir, Bit32u * clustNum, bool parDir); 200 bool getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry); 201 bool addDirectoryEntry(Bit32u dirClustNumber, direntry useEntry); 202 void zeroOutCluster(Bit32u clustNumber); 203 bool getEntryName(char *fullname, char *entname); 204 205 bootstrap bootbuffer; 206 bool absolute; 207 Bit8u fattype; 208 Bit32u CountOfClusters; 209 Bit32u partSectOff; 210 Bit32u firstDataSector; 211 Bit32u firstRootDirSect; 212 213 Bit32u cwdDirCluster; 214 215 Bit8u fatSectBuffer[1024]; 216 Bit32u curFatSect; 217 }; 218 219 class cdromDrive final : public localDrive 220 { 221 public: 222 cdromDrive(const char _driveLetter, const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid, int& error); 223 virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); 224 virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); 225 virtual bool FileUnlink(char * name); 226 virtual bool RemoveDir(char * dir); 227 virtual bool MakeDir(char * dir); 228 virtual bool Rename(char * oldname,char * newname); 229 virtual bool GetFileAttr(char * name,Bit16u * attr); 230 virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); 231 virtual void SetDir(const char* path); 232 virtual bool isRemote(void); 233 virtual bool isRemovable(void); 234 virtual Bits UnMount(void); 235 private: 236 Bit8u subUnit; 237 char driveLetter; 238 }; 239 240 #ifdef _MSC_VER 241 #pragma pack (1) 242 #endif 243 struct isoPVD { 244 Bit8u type; 245 Bit8u standardIdent[5]; 246 Bit8u version; 247 Bit8u unused1; 248 Bit8u systemIdent[32]; 249 Bit8u volumeIdent[32]; 250 Bit8u unused2[8]; 251 Bit32u volumeSpaceSizeL; 252 Bit32u volumeSpaceSizeM; 253 Bit8u unused3[32]; 254 Bit16u volumeSetSizeL; 255 Bit16u volumeSetSizeM; 256 Bit16u volumeSeqNumberL; 257 Bit16u volumeSeqNumberM; 258 Bit16u logicBlockSizeL; 259 Bit16u logicBlockSizeM; 260 Bit32u pathTableSizeL; 261 Bit32u pathTableSizeM; 262 Bit32u locationPathTableL; 263 Bit32u locationOptPathTableL; 264 Bit32u locationPathTableM; 265 Bit32u locationOptPathTableM; 266 Bit8u rootEntry[34]; 267 Bit32u unused4[1858]; 268 } GCC_ATTRIBUTE(packed); 269 270 struct isoDirEntry { 271 Bit8u length; 272 Bit8u extAttrLength; 273 Bit32u extentLocationL; 274 Bit32u extentLocationM; 275 Bit32u dataLengthL; 276 Bit32u dataLengthM; 277 Bit8u dateYear; 278 Bit8u dateMonth; 279 Bit8u dateDay; 280 Bit8u timeHour; 281 Bit8u timeMin; 282 Bit8u timeSec; 283 Bit8u timeZone; 284 Bit8u fileFlags; 285 Bit8u fileUnitSize; 286 Bit8u interleaveGapSize; 287 Bit16u VolumeSeqNumberL; 288 Bit16u VolumeSeqNumberM; 289 Bit8u fileIdentLength; 290 Bit8u ident[222]; 291 } GCC_ATTRIBUTE(packed); 292 293 #ifdef _MSC_VER 294 #pragma pack () 295 #endif 296 297 #if defined (WORDS_BIGENDIAN) 298 #define EXTENT_LOCATION(de) ((de).extentLocationM) 299 #define DATA_LENGTH(de) ((de).dataLengthM) 300 #else 301 #define EXTENT_LOCATION(de) ((de).extentLocationL) 302 #define DATA_LENGTH(de) ((de).dataLengthL) 303 #endif 304 305 #define ISO_FRAMESIZE 2048 306 #define ISO_ASSOCIATED 4 307 #define ISO_DIRECTORY 2 308 #define ISO_HIDDEN 1 309 #define ISO_MAX_FILENAME_LENGTH 37 310 #define ISO_MAXPATHNAME 256 311 #define ISO_FIRST_VD 16 312 #define IS_ASSOC(fileFlags) (fileFlags & ISO_ASSOCIATED) 313 #define IS_DIR(fileFlags) (fileFlags & ISO_DIRECTORY) 314 #define IS_HIDDEN(fileFlags) (fileFlags & ISO_HIDDEN) 315 #define ISO_MAX_HASH_TABLE_SIZE 100 316 317 class isoDrive final : public DOS_Drive { 318 public: 319 isoDrive(char driveLetter, const char* device_name, Bit8u mediaid, int &error); 320 ~isoDrive(); 321 virtual bool FileOpen(DOS_File **file, char *name, Bit32u flags); 322 virtual bool FileCreate(DOS_File **file, char *name, Bit16u attributes); 323 virtual bool FileUnlink(char *name); 324 virtual bool RemoveDir(char *dir); 325 virtual bool MakeDir(char *dir); 326 virtual bool TestDir(char *dir); 327 virtual bool FindFirst(char *_dir, DOS_DTA &dta, bool fcb_findfirst); 328 virtual bool FindNext(DOS_DTA &dta); 329 virtual bool GetFileAttr(char *name, Bit16u *attr); 330 virtual bool Rename(char * oldname,char * newname); 331 virtual bool AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters); 332 virtual bool FileExists(const char *name); 333 virtual bool FileStat(const char *name, FileStat_Block *const stat_block); 334 virtual Bit8u GetMediaByte(void); EmptyCache(void)335 virtual void EmptyCache(void){} 336 virtual bool isRemote(void); 337 virtual bool isRemovable(void); 338 virtual Bits UnMount(void); 339 bool readSector(Bit8u *buffer, Bit32u sector); GetLabel()340 virtual const char *GetLabel() { return discLabel; } 341 virtual void Activate(void); 342 private: 343 int readDirEntry(isoDirEntry *de, Bit8u *data); 344 bool loadImage(); 345 bool lookupSingle(isoDirEntry *de, const char *name, Bit32u sectorStart, Bit32u length); 346 bool lookup(isoDirEntry *de, const char *path); 347 int UpdateMscdex(char driveLetter, const char* physicalPath, Bit8u& subUnit); 348 int GetDirIterator(const isoDirEntry* de); 349 bool GetNextDirEntry(const int dirIterator, isoDirEntry* de); 350 void FreeDirIterator(const int dirIterator); 351 bool ReadCachedSector(Bit8u** buffer, const Bit32u sector); 352 353 struct DirIterator { 354 bool valid; 355 bool root; 356 Bit32u currentSector; 357 Bit32u endSector; 358 Bit32u pos; 359 } dirIterators[MAX_OPENDIRS]; 360 361 int nextFreeDirIterator; 362 363 struct SectorHashEntry { 364 bool valid; 365 Bit32u sector; 366 Bit8u data[ISO_FRAMESIZE]; 367 } sectorHashEntries[ISO_MAX_HASH_TABLE_SIZE]; 368 369 bool iso; 370 bool dataCD; 371 isoDirEntry rootEntry; 372 Bit8u mediaid; 373 char fileName[CROSS_LEN]; 374 Bit8u subUnit; 375 char driveLetter; 376 char discLabel[32]; 377 }; 378 379 struct VFILE_Block; 380 381 class Virtual_Drive final : public DOS_Drive { 382 public: 383 Virtual_Drive(); 384 bool FileOpen(DOS_File * * file,char * name,Bit32u flags); 385 bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); 386 bool FileUnlink(char * name); 387 bool RemoveDir(char * dir); 388 bool MakeDir(char * dir); 389 bool TestDir(char * dir); 390 bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst); 391 bool FindNext(DOS_DTA & dta); 392 bool GetFileAttr(char * name,Bit16u * attr); 393 bool Rename(char * oldname,char * newname); 394 bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); 395 bool FileExists(const char* name); 396 bool FileStat(const char* name, FileStat_Block* const stat_block); 397 Bit8u GetMediaByte(void); EmptyCache(void)398 void EmptyCache(void){} 399 bool isRemote(void); 400 virtual bool isRemovable(void); 401 virtual Bits UnMount(void); 402 virtual char const* GetLabel(void); 403 private: 404 Virtual_Drive(const Virtual_Drive&); // prevent copying 405 Virtual_Drive& operator= (const Virtual_Drive&); // prevent assignment 406 VFILE_Block * search_file; 407 }; 408 409 class Overlay_Drive final : public localDrive { 410 public: 411 Overlay_Drive(const char *startdir, 412 const char *overlay, 413 uint16_t _bytes_sector, 414 uint8_t _sectors_cluster, 415 uint16_t _total_clusters, 416 uint16_t _free_clusters, 417 uint8_t _mediaid, 418 uint8_t &error); 419 420 virtual bool FileOpen(DOS_File **file, char *name, uint32_t flags); 421 virtual bool FileCreate(DOS_File * * file,char * name,Bit16u /*attributes*/); 422 virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst); 423 virtual bool FindNext(DOS_DTA & dta); 424 virtual bool FileUnlink(char * name); 425 virtual bool GetFileAttr(char * name,Bit16u * attr); 426 virtual bool FileExists(const char* name); 427 virtual bool Rename(char * oldname,char * newname); 428 virtual bool FileStat(const char* name, FileStat_Block * const stat_block); 429 virtual void EmptyCache(void); 430 431 FILE *create_file_in_overlay(const char *dos_filename, char const *mode); 432 433 virtual Bits UnMount(void); 434 virtual bool TestDir(char * dir); 435 virtual bool RemoveDir(char * dir); 436 virtual bool MakeDir(char * dir); 437 private: 438 char overlaydir[CROSS_LEN]; 439 bool Sync_leading_dirs(const char* dos_filename); 440 void add_DOSname_to_cache(const char* name); 441 void remove_DOSname_from_cache(const char* name); 442 void add_DOSdir_to_cache(const char* name); 443 void remove_DOSdir_from_cache(const char* name); 444 void update_cache(bool read_directory_contents = false); 445 446 std::vector<std::string> deleted_files_in_base; //Set is probably better, or some other solution (involving the disk). 447 std::vector<std::string> deleted_paths_in_base; //Currently only used to hide the overlay folder. 448 std::string overlap_folder; 449 void add_deleted_file(const char* name, bool create_on_disk); 450 void remove_deleted_file(const char* name, bool create_on_disk); 451 bool is_deleted_file(const char* name); 452 void add_deleted_path(const char* name, bool create_on_disk); 453 void remove_deleted_path(const char* name, bool create_on_disk); 454 bool is_deleted_path(const char* name); 455 bool check_if_leading_is_deleted(const char* name); 456 457 bool is_dir_only_in_overlay(const char* name); //cached 458 459 460 void remove_special_file_from_disk(const char* dosname, const char* operation); 461 void add_special_file_to_disk(const char* dosname, const char* operation); 462 std::string create_filename_of_special_operation(const char* dosname, const char* operation); 463 void convert_overlay_to_DOSname_in_base(char* dirname ); 464 //For caching the update_cache routine. 465 std::vector<std::string> DOSnames_cache; //Also set is probably better. 466 std::vector<std::string> DOSdirs_cache; //Can not blindly change its type. it is important that subdirs come after the parent directory. 467 const std::string special_prefix; 468 }; 469 470 #endif 471