diff --git a/include/drives.h b/include/drives.h index daa08c35..dec9f266 100644 --- a/include/drives.h +++ b/include/drives.h @@ -22,6 +22,7 @@ #include "dosbox.h" #include +#include #include #include @@ -75,6 +76,7 @@ public: virtual bool isRemovable(void); virtual Bits UnMount(void); const char* getBasedir() {return basedir;}; + virtual bool isNewWriteProtectedFile(const std::string& filename); protected: char basedir[CROSS_LEN]; struct { @@ -82,6 +84,7 @@ protected: } srchInfo[MAX_OPENDIRS]; private: + std::set write_protected_files; struct { Bit16u bytes_sector; Bit8u sectors_cluster; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 1fac1aaa..f907046c 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -62,8 +62,14 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u /*attributes*/) return true; } -bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { - const char* type; +bool localDrive::isNewWriteProtectedFile(const std::string& filename){ + const std::pair::iterator, bool> \ + ret(write_protected_files.insert(filename)); + return ret.second; +} + +bool localDrive::FileOpen(DOS_File** file, char * name, Bit32u flags) { + const char* type = nullptr; switch (flags&0xf) { case OPEN_READ: type = "rb" ; break; case OPEN_WRITE: type = "rb+"; break; @@ -81,37 +87,46 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { //Flush the buffer of handles for the same file. (Betrayal in Antara) Bit8u i,drive=DOS_DRIVES; - localFile *lfp; - for (i=0;iIsOpen() && Files[i]->GetDrive()==drive && Files[i]->IsName(name)) { lfp=dynamic_cast(Files[i]); if (lfp) lfp->Flush(); } } - FILE * hand = fopen_wrap(newname,type); -// Bit32u err=errno; - if (!hand) { - if((flags&0xf) != OPEN_READ) { - FILE * hmm = fopen_wrap(newname,"rb"); - if (hmm) { - fclose(hmm); - LOG_MSG("Warning: file %s exists and failed to open in write mode.\nPlease Remove write-protection",newname); + FILE* fhandle = fopen(newname, type); + // Was the file was opened with the desired type? + if (!fhandle) { + // No; but do the requested flags require write-access? + if ((flags & 0xf) != OPEN_READ) { + // Yes; maybe the local file is simply be protected, so try again with read-only + fhandle = fopen_wrap(newname, "rb"); + if (fhandle) { + // Ok! so the file is protected file; fool the DOS program into thinking its OK + flags &= ~OPEN_READWRITE; + // Inform the user that the file is being protected against modification. + // If the DOS program /really/ needs to write to the file, it will crash/exit + // and this will be one of the last messages on the screen, so the user can + // decide to un-write-protect the file if they wish. + if (isNewWriteProtectedFile(newname)) { + LOG_MSG("FILESYSTEM: protected from modification: %s", newname); + } } } - return false; } - *file=new localFile(name,hand); - (*file)->flags=flags; //for the inheritance flag and maybe check for others. -// (*file)->SetFileName(newname); - return true; + if (fhandle) { + *file = new localFile(name, fhandle); + (*file)->flags=flags; //for the inheritance flag and maybe check for others. + } + return (fhandle != NULL); } FILE * localDrive::GetSystemFilePtr(char const * const name, char const * const type) {