2020-03-04 16:55:40 +01:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
|
2021-01-17 17:43:17 +01:00
|
|
|
if (::access(_device.constData(), W_OK) != 0)
|
2020-03-04 16:55:40 +01:00
|
|
|
{
|
|
|
|
/* Not running as root, try to outsource formatting to udisks2 */
|
|
|
|
|
2020-05-25 00:36:16 +02:00
|
|
|
#ifndef QT_NO_DBUS
|
2020-03-04 16:55:40 +01:00
|
|
|
UDisks2Api udisks2;
|
|
|
|
if (udisks2.formatDrive(_device))
|
|
|
|
{
|
|
|
|
emit success();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-25 00:36:16 +02:00
|
|
|
#endif
|
2020-03-04 16:55:40 +01:00
|
|
|
emit error(tr("Error formatting (through udisks2)"));
|
2020-05-25 00:36:16 +02:00
|
|
|
#ifndef QT_NO_DBUS
|
2020-03-04 16:55:40 +01:00
|
|
|
}
|
2020-05-25 00:36:16 +02:00
|
|
|
#endif
|
2020-03-04 16:55:40 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-06-01 17:45:41 +02:00
|
|
|
proc.execute("partprobe", QStringList() );
|
2020-03-04 16:55:40 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|