Skip to content

Commit

Permalink
Check for write permissions for some key files (#1972)
Browse files Browse the repository at this point in the history
* check if an nds save file can be opened for writing

also add the ability to open a file in append mode

* fix multi-instance saves

also move the check for file writability into a separate function (probably uneeded?)

* implement check for gba roms

* move rom load error messages into the functions

also finish gba slot (oops)

* improve error string

* check write perms before saving path settings

* fix memory leak

* check for writability of firmware/nand/sds

* add secondary checks for nand/firmware

* add check for config file being writable

* Return the file write error as a QString to avoid the invalid char*
causing a garbled error message.

Qt wants it as QString either way.
  • Loading branch information
Jaklyy authored Feb 7, 2024
1 parent 71e1ba8 commit 5ffa642
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 50 deletions.
12 changes: 12 additions & 0 deletions src/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ enum FileMode : unsigned {
*/
Text = 0b01'00'00,

/**
* Opens a file in append mode.
*/
Append = 0b10'00'00,

/**
* Opens a file for reading and writing.
* Equivalent to <tt>Read | Write</tt>.
Expand Down Expand Up @@ -201,6 +206,13 @@ FileHandle* OpenLocalFile(const std::string& path, FileMode mode);
bool FileExists(const std::string& name);
bool LocalFileExists(const std::string& name);

// Returns true if we have permission to write to the file.
// Warning: Also creates the file if not present!
bool CheckFileWritable(const std::string& filepath);

// Same as above (CheckFileWritable()) but for local files.
bool CheckLocalFileWritable(const std::string& filepath);

/** Close a file opened with \c OpenFile.
* @returns \c true if the file was closed successfully, false otherwise.
* @post \c file is no longer valid and should not be used.
Expand Down
23 changes: 16 additions & 7 deletions src/frontend/qt_sdl/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,19 +378,25 @@ ConfigEntry ConfigFile[] =
};


void LoadFile(int inst)
bool LoadFile(int inst, int actualinst)
{
Platform::FileHandle* f;
if (inst > 0)
{
char name[100] = {0};
snprintf(name, 99, kUniqueConfigFile, inst+1);
f = Platform::OpenLocalFile(name, Platform::FileMode::ReadText);

if (!Platform::CheckLocalFileWritable(name)) return false;
}
else
{
f = Platform::OpenLocalFile(kConfigFile, Platform::FileMode::ReadText);

if (!f) return;
if (actualinst == 0 && !Platform::CheckLocalFileWritable(kConfigFile)) return false;
}

if (!f) return true;

char linebuf[1024];
char entryname[32];
Expand Down Expand Up @@ -425,9 +431,10 @@ void LoadFile(int inst)
}

CloseFile(f);
return true;
}

void Load()
bool Load()
{

for (ConfigEntry* entry = &ConfigFile[0]; entry->Value; entry++)
Expand All @@ -440,12 +447,14 @@ void Load()
case 3: *(int64_t*)entry->Value = std::get<int64_t>(entry->Default); break;
}
}

LoadFile(0);


int inst = Platform::InstanceID();

bool ret = LoadFile(0, inst);
if (inst > 0)
LoadFile(inst);
ret = LoadFile(inst, inst);

return ret;
}

void Save()
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/qt_sdl/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ extern bool GdbARM7BreakOnStartup;
extern bool GdbARM9BreakOnStartup;


void Load();
bool Load();
void Save();

}
Expand Down
32 changes: 32 additions & 0 deletions src/frontend/qt_sdl/EmuSettingsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,12 @@ void EmuSettingsDialog::on_btnFirmwareBrowse_clicked()

if (file.isEmpty()) return;

if (!Platform::CheckFileWritable(file.toStdString()))
{
QMessageBox::critical(this, "melonDS", "Unable to write to firmware file.\nPlease check file/folder write permissions.");
return;
}

updateLastBIOSFolder(file);

ui->txtFirmwarePath->setText(file);
Expand Down Expand Up @@ -436,6 +442,12 @@ void EmuSettingsDialog::on_btnDLDISDBrowse_clicked()

if (file.isEmpty()) return;

if (!Platform::CheckFileWritable(file.toStdString()))
{
QMessageBox::critical(this, "melonDS", "Unable to write to DLDI SD image.\nPlease check file/folder write permissions.");
return;
}

updateLastBIOSFolder(file);

ui->txtDLDISDPath->setText(file);
Expand Down Expand Up @@ -468,6 +480,13 @@ void EmuSettingsDialog::on_btnDSiFirmwareBrowse_clicked()

if (file.isEmpty()) return;

if (!Platform::CheckFileWritable(file.toStdString()))
{
QMessageBox::critical(this, "melonDS", "Unable to write to DSi firmware file.\nPlease check file/folder write permissions.");
return;
}


updateLastBIOSFolder(file);

ui->txtDSiFirmwarePath->setText(file);
Expand All @@ -482,6 +501,13 @@ void EmuSettingsDialog::on_btnDSiNANDBrowse_clicked()

if (file.isEmpty()) return;

if (!Platform::CheckFileWritable(file.toStdString()))
{
QMessageBox::critical(this, "melonDS", "Unable to write to DSi NAND image.\nPlease check file/folder write permissions.");
return;
}


updateLastBIOSFolder(file);

ui->txtDSiNANDPath->setText(file);
Expand Down Expand Up @@ -510,6 +536,12 @@ void EmuSettingsDialog::on_btnDSiSDBrowse_clicked()

if (file.isEmpty()) return;

if (!Platform::CheckFileWritable(file.toStdString()))
{
QMessageBox::critical(this, "melonDS", "Unable to write to DSi SD image.\nPlease check file/folder write permissions.");
return;
}

updateLastBIOSFolder(file);

ui->txtDSiSDPath->setText(file);
Expand Down
20 changes: 20 additions & 0 deletions src/frontend/qt_sdl/PathSettingsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <stdio.h>
#include <QFileDialog>
#include <QMessageBox>
#include <QTemporaryFile>

#include "types.h"
#include "Config.h"
Expand All @@ -37,6 +38,7 @@ extern bool RunningSomething;

bool PathSettingsDialog::needsReset = false;

constexpr char errordialog[] = "melonDS cannot write to that directory.";

PathSettingsDialog::PathSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::PathSettingsDialog)
{
Expand Down Expand Up @@ -101,6 +103,12 @@ void PathSettingsDialog::on_btnSaveFileBrowse_clicked()
QString::fromStdString(EmuDirectory));

if (dir.isEmpty()) return;

if (!QTemporaryFile(dir).open())
{
QMessageBox::critical(this, "melonDS", errordialog);
return;
}

ui->txtSaveFilePath->setText(dir);
}
Expand All @@ -112,6 +120,12 @@ void PathSettingsDialog::on_btnSavestateBrowse_clicked()
QString::fromStdString(EmuDirectory));

if (dir.isEmpty()) return;

if (!QTemporaryFile(dir).open())
{
QMessageBox::critical(this, "melonDS", errordialog);
return;
}

ui->txtSavestatePath->setText(dir);
}
Expand All @@ -123,6 +137,12 @@ void PathSettingsDialog::on_btnCheatFileBrowse_clicked()
QString::fromStdString(EmuDirectory));

if (dir.isEmpty()) return;

if (!QTemporaryFile(dir).open())
{
QMessageBox::critical(this, "melonDS", errordialog);
return;
}

ui->txtCheatFilePath->setText(dir);
}
28 changes: 27 additions & 1 deletion src/frontend/qt_sdl/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ std::string InstanceFileSuffix()

constexpr char AccessMode(FileMode mode, bool file_exists)
{

if (mode & FileMode::Append)
return 'a';

if (!(mode & FileMode::Write))
// If we're only opening the file for reading...
return 'r';
Expand Down Expand Up @@ -255,7 +259,7 @@ static std::string GetModeString(FileMode mode, bool file_exists)

FileHandle* OpenFile(const std::string& path, FileMode mode)
{
if ((mode & FileMode::ReadWrite) == FileMode::None)
if ((mode & (FileMode::ReadWrite | FileMode::Append)) == FileMode::None)
{ // If we aren't reading or writing, then we can't open the file
Log(LogLevel::Error, "Attempted to open \"%s\" in neither read nor write mode (FileMode 0x%x)\n", path.c_str(), mode);
return nullptr;
Expand Down Expand Up @@ -327,6 +331,28 @@ bool LocalFileExists(const std::string& name)
return true;
}

bool CheckFileWritable(const std::string& filepath)
{
FileHandle* file = Platform::OpenFile(filepath.c_str(), FileMode::Append);
if (file)
{
Platform::CloseFile(file);
return true;
}
else return false;
}

bool CheckLocalFileWritable(const std::string& name)
{
FileHandle* file = Platform::OpenLocalFile(name.c_str(), FileMode::Append);
if (file)
{
Platform::CloseFile(file);
return true;
}
else return false;
}

bool FileSeek(FileHandle* file, s64 offset, FileSeekOrigin origin)
{
int stdorigin;
Expand Down
Loading

0 comments on commit 5ffa642

Please sign in to comment.