mirror of
https://github.com/cmclark00/retro-imager.git
synced 2025-05-18 07:55:21 +01:00
- Adds "hidden" shift+ctrl+X shortcut for eXpert image customization options. Allows one to set certain options on RPI OS images, namely: * disable overscan * set hostname * enable ssh and - set Pi user password if using password authentication OR - set authorized_keys (if running Imager on Linux/Mac this will have contents of ~/.ssh/id_rsa.pub prefilled) * configure wifi settings (if computer running Imager is connected by wifi it will prefill wifi SSID and if on Windows also PSK). * set time zone and keyboard layout Related to feature requests/issues: Ref #127 Ref #86 Ref #102 Ref #73 Ref #68 Ref #25 Ref #12 - Option Window also allows setting a couple other general settings: * Adds option for audible notification (beep) when imaging completes. Closes #46 * Adds option not to eject media when done. Closes #144 - No longer suspends a number of Windows services during Imaging (We want Windows to detect the drive and mount it, or we may not be able to alter files on FAT partition).
215 lines
5.9 KiB
C++
215 lines
5.9 KiB
C++
/*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright (C) 2020 Raspberry Pi (Trading) Limited
|
|
*/
|
|
|
|
#include "driveformatthread.h"
|
|
#include "dependencies/drivelist/src/drivelist.hpp"
|
|
#include "dependencies/mountutils/src/mountutils.hpp"
|
|
#include <regex>
|
|
#include <QDebug>
|
|
#include <QProcess>
|
|
#include <QTemporaryFile>
|
|
#include <QCoreApplication>
|
|
|
|
#ifdef Q_OS_LINUX
|
|
#include "linux/udisks2api.h"
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
DriveFormatThread::DriveFormatThread(const QByteArray &device, QObject *parent)
|
|
: QThread(parent), _device(device)
|
|
{
|
|
|
|
}
|
|
|
|
DriveFormatThread::~DriveFormatThread()
|
|
{
|
|
wait();
|
|
}
|
|
|
|
void DriveFormatThread::run()
|
|
{
|
|
#ifdef Q_OS_WIN
|
|
std::regex windriveregex("\\\\\\\\.\\\\PHYSICALDRIVE([0-9]+)", std::regex_constants::icase);
|
|
std::cmatch m;
|
|
|
|
if (std::regex_match(_device.constData(), m, windriveregex))
|
|
{
|
|
QByteArray nr = QByteArray::fromStdString(m[1]);
|
|
|
|
qDebug() << "Formatting Windows drive #" << nr << "(" << _device << ")";
|
|
|
|
QProcess proc;
|
|
QByteArray diskpartCmds =
|
|
"select disk "+nr+"\r\n"
|
|
"clean\r\n"
|
|
"create partition primary\r\n"
|
|
"select partition 1\r\n"
|
|
"set id=0e\r\n"
|
|
"assign\r\n";
|
|
proc.start("diskpart");
|
|
proc.waitForStarted();
|
|
proc.write(diskpartCmds);
|
|
proc.closeWriteChannel();
|
|
proc.waitForFinished();
|
|
|
|
QByteArray output = proc.readAllStandardError();
|
|
qDebug() << output;
|
|
qDebug() << "Done running diskpart. Exit status code =" << proc.exitCode();
|
|
|
|
if (proc.exitCode())
|
|
{
|
|
emit error(tr("Error partitioning: %1").arg(QString(output)));
|
|
}
|
|
else
|
|
{
|
|
auto l = Drivelist::ListStorageDevices();
|
|
QByteArray devlower = _device.toLower();
|
|
for (auto i : l)
|
|
{
|
|
if (QByteArray::fromStdString(i.device).toLower() == devlower && i.mountpoints.size() == 1)
|
|
{
|
|
QByteArray driveLetter = QByteArray::fromStdString(i.mountpoints.front());
|
|
if (driveLetter.endsWith("\\"))
|
|
driveLetter.chop(1);
|
|
qDebug() << "Drive letter of device:" << driveLetter;
|
|
|
|
QProcess f32format;
|
|
QStringList args;
|
|
args << "-y" << driveLetter;
|
|
f32format.start(QCoreApplication::applicationDirPath()+"/fat32format.exe", args);
|
|
if (!f32format.waitForStarted())
|
|
{
|
|
emit error(tr("Error starting fat32format"));
|
|
return;
|
|
}
|
|
|
|
//f32format.write("y\r\n");
|
|
f32format.closeWriteChannel();
|
|
f32format.waitForFinished(120000);
|
|
|
|
if (f32format.exitStatus() || f32format.exitCode())
|
|
{
|
|
emit error(tr("Error running fat32format: %1").arg(QString(f32format.readAll())));
|
|
}
|
|
else
|
|
{
|
|
emit success();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
emit error(tr("Error determining new drive letter"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
emit error(tr("Invalid device: %1").arg(QString(_device)));
|
|
}
|
|
#elif defined(Q_OS_DARWIN)
|
|
QProcess proc;
|
|
QStringList args;
|
|
args << "eraseDisk" << "FAT32" << "SDCARD" << "MBRFormat" << _device;
|
|
proc.start("diskutil", args);
|
|
proc.waitForFinished();
|
|
|
|
QByteArray output = proc.readAllStandardError();
|
|
qDebug() << args;
|
|
qDebug() << "diskutil output:" << output;
|
|
|
|
if (proc.exitCode())
|
|
{
|
|
emit error(tr("Error partitioning: %1").arg(QString(output)));
|
|
}
|
|
else
|
|
{
|
|
emit success();
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (::access(_device.constData(), W_OK) != 0)
|
|
{
|
|
/* Not running as root, try to outsource formatting to udisks2 */
|
|
|
|
#ifndef QT_NO_DBUS
|
|
UDisks2Api udisks2;
|
|
if (udisks2.formatDrive(_device))
|
|
{
|
|
emit success();
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
emit error(tr("Error formatting (through udisks2)"));
|
|
#ifndef QT_NO_DBUS
|
|
}
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
QProcess proc;
|
|
QByteArray partitionTable;
|
|
QStringList args;
|
|
QByteArray fatpartition = _device;
|
|
partitionTable = "8192,,0E\n"
|
|
"0,0\n"
|
|
"0,0\n"
|
|
"0,0\n";
|
|
args << "-uS" << _device;
|
|
if (isdigit(fatpartition.at(fatpartition.length()-1)))
|
|
fatpartition += "p1";
|
|
else
|
|
fatpartition += "1";
|
|
|
|
unmount_disk(_device);
|
|
proc.setProcessChannelMode(proc.MergedChannels);
|
|
proc.start("sfdisk", args);
|
|
if (!proc.waitForStarted())
|
|
{
|
|
emit error(tr("Error starting sfdisk"));
|
|
return;
|
|
}
|
|
proc.write(partitionTable);
|
|
proc.closeWriteChannel();
|
|
proc.waitForFinished();
|
|
QByteArray output = proc.readAll();
|
|
qDebug() << "sfdisk:" << output;
|
|
|
|
if (proc.exitCode())
|
|
{
|
|
emit error(tr("Error partitioning: %1").arg(QString(output)));
|
|
return;
|
|
}
|
|
|
|
proc.execute("partprobe", QStringList() );
|
|
|
|
args.clear();
|
|
args << fatpartition;
|
|
proc.start("mkfs.fat", args);
|
|
if (!proc.waitForStarted())
|
|
{
|
|
emit error(tr("Error starting mkfs.fat"));
|
|
return;
|
|
}
|
|
|
|
proc.waitForFinished();
|
|
output = proc.readAll();
|
|
qDebug() << "mkfs.fat:" << output;
|
|
|
|
if (proc.exitCode())
|
|
{
|
|
emit error(tr("Error running mkfs.fat: %1").arg(QString(output)));
|
|
return;
|
|
}
|
|
|
|
emit success();
|
|
|
|
#else
|
|
emit error(tr("Formatting not implemented for this platform"));
|
|
#endif
|
|
}
|