From 7e4f5c9045299a3fa60cc527cd97532f7004f9e6 Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Tue, 21 Jul 2020 15:04:38 +0200 Subject: [PATCH] Mac: open preferences for user if Imager is not allowed access Normally the system will prompt the user to allow Imager access to removable volumes. Open preferences and ask user to allow Imager manually in a corner case in which this does not occur. --- downloadthread.cpp | 13 +++++++++++-- mac/macfile.cpp | 12 ++++++------ mac/macfile.h | 4 +++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/downloadthread.cpp b/downloadthread.cpp index c0d1c3a..cabf308 100644 --- a/downloadthread.cpp +++ b/downloadthread.cpp @@ -171,8 +171,17 @@ bool DownloadThread::_openAndPrepareDevice() #ifdef Q_OS_DARWIN _filename.replace("/dev/disk", "/dev/rdisk"); - if (!_file.authOpen(_filename)) { - emit error(tr("Error running authopen to gain access to disk device '%1'").arg(QString(_filename))); + auto authopenresult = _file.authOpen(_filename); + + if (authopenresult == _file.authOpenCancelled) { + /* User cancelled authentication */ + emit error(tr("Authentication cancelled")); + return false; + } else if (authopenresult == _file.authOpenError) { + QString msg = tr("Error running authopen to gain access to disk device '%1'").arg(QString(_filename)); + msg += "
"+tr("Please verify if 'Raspberry Pi Imager' is allowed access to 'removable volumes' in privacy settings (under 'files and folders' or alternatively give it 'full disk access')."); + QProcess::execute("open x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles"); + emit error(msg); return false; } #else diff --git a/mac/macfile.cpp b/mac/macfile.cpp index 7f890b9..91529db 100644 --- a/mac/macfile.cpp +++ b/mac/macfile.cpp @@ -22,7 +22,7 @@ bool MacFile::isSequential() const return false; } -bool MacFile::authOpen(const QByteArray &filename) +MacFile::authOpenResult MacFile::authOpen(const QByteArray &filename) { int fd = -1; @@ -34,13 +34,13 @@ bool MacFile::authOpen(const QByteArray &filename) kAuthorizationFlagPreAuthorize; AuthorizationRef authRef; if (AuthorizationCreate(&rights, nullptr, flags, &authRef) != 0) - return false; + return authOpenCancelled; AuthorizationExternalForm externalForm; if (AuthorizationMakeExternalForm(authRef, &externalForm) != 0) { AuthorizationFree(authRef, 0); - return false; + return authOpenError; } const char *cmd = "/usr/libexec/authopen"; @@ -110,17 +110,17 @@ bool MacFile::authOpen(const QByteArray &filename) if (wpid == -1) { qDebug() << "waitpid() failed executing authopen"; - return false; + return authOpenError; } if (WEXITSTATUS(status)) { qDebug() << "authopen returned failure code" << WEXITSTATUS(status); - return false; + return authOpenError; } qDebug() << "fd received:" << fd; } AuthorizationFree(authRef, 0); - return open(fd, QIODevice::ReadWrite | QIODevice::ExistingOnly | QIODevice::Unbuffered, QFileDevice::AutoCloseHandle); + return open(fd, QIODevice::ReadWrite | QIODevice::ExistingOnly | QIODevice::Unbuffered, QFileDevice::AutoCloseHandle) ? authOpenSuccess : authOpenError; } diff --git a/mac/macfile.h b/mac/macfile.h index 6bc842a..b24dd3d 100644 --- a/mac/macfile.h +++ b/mac/macfile.h @@ -12,9 +12,11 @@ class MacFile : public QFile { Q_OBJECT public: + enum authOpenResult {authOpenCancelled, authOpenSuccess, authOpenError }; + MacFile(QObject *parent = nullptr); virtual bool isSequential() const; - bool authOpen(const QByteArray &filename); + authOpenResult authOpen(const QByteArray &filename); }; #endif // MACFILE_H