1
0
Fork 0

Permit the use of protected game data files

Many DOS games open all their files in write-mode regardless if the
game actually intends to write to them or not.

This can result the files' metadata being updated (lossing the
original date-stamp) as well as putting the file at-risk of
corruption if the game crashes with the file open for writing.

Under the existing DOSBox implementation, if a user attempts to
write-protect their data files then DOSBox will quit with an error in
the above scenario.

This commit allows the use of write-protected files (similar to
running a game from CDROM) and indicates which files are being
actively protected against modification.

Typically the only files that need to be left writable are those that
the game actually changes, such as: save-game files, highscore
files, in-game settings, and so on.  If these are also protected,
then the game will quit/crash immediately after the protected message
is printed, and thus indicate which file require write-allowance.
This commit is contained in:
krcroft 2020-01-23 17:46:03 -08:00
parent 6804faf931
commit c730e5d70a
No known key found for this signature in database
GPG key ID: 4AD3678F4A2C291C
2 changed files with 38 additions and 20 deletions

View file

@ -22,6 +22,7 @@
#include "dosbox.h"
#include <memory>
#include <set>
#include <string>
#include <vector>
@ -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<std::string> write_protected_files;
struct {
Bit16u bytes_sector;
Bit8u sectors_cluster;

View file

@ -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<std::set<std::string>::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;i<DOS_DRIVES;i++) {
if (Drives[i]==this) {
drive=i;
localFile *lfp = nullptr;
for (i = 0; i < DOS_DRIVES; i++) {
if (Drives[i] == this) {
drive = i;
break;
}
}
for (i=0;i<DOS_FILES;i++) {
for (i = 0; i < DOS_FILES; i++) {
if (Files[i] && Files[i]->IsOpen() && Files[i]->GetDrive()==drive && Files[i]->IsName(name)) {
lfp=dynamic_cast<localFile*>(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) {