From 6a78a7451501fda2547babdd28e9d896286fb5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 18 Aug 2017 14:45:15 +0300 Subject: [PATCH] Add support for creating file systems with label. Some file systems such as UDF or F2FS only support writing labels when creating them. At the moment this only works in new partition dialog and not in the partition properties dialog. --- src/fs/filesystem.cpp | 15 ++++++ src/fs/filesystem.h | 4 ++ src/fs/udf.cpp | 80 ++++++++++++++++++++++---------- src/fs/udf.h | 7 +++ src/jobs/createfilesystemjob.cpp | 12 +++-- src/jobs/createfilesystemjob.h | 3 +- src/ops/newoperation.cpp | 2 +- 7 files changed, 93 insertions(+), 30 deletions(-) diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index 307cb96..1ce8391 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -173,6 +173,21 @@ bool FileSystem::create(Report& report, const QString& deviceNode) return true; } +/** Creates a new FileSystem with a specified Label + @param report Report to write status information to + @param deviceNode the device node for the Partition to create the FileSystem on + @param label the new label for the FileSystem + @return true if successful +*/ +bool FileSystem::createWithLabel(Report& report, const QString& deviceNode, const QString& label) +{ + Q_UNUSED(report) + Q_UNUSED(deviceNode) + Q_UNUSED(label) + + return true; +} + /** Scans a new FileSystem and load file system specific class variables. * @param deviceNode the device node for the Partition to create the FileSystem on */ diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index 8411f83..a578992 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -113,6 +113,7 @@ public: virtual qint64 readUsedCapacity(const QString& deviceNode) const; virtual QString readLabel(const QString& deviceNode) const; virtual bool create(Report& report, const QString& deviceNode); + virtual bool createWithLabel(Report& report, const QString& deviceNode, const QString& label); virtual bool resize(Report& report, const QString& deviceNode, qint64 newLength) const; virtual bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 newLength) const; virtual bool move(Report& report, const QString& deviceNode, qint64 newStartSector) const; @@ -135,6 +136,9 @@ public: virtual CommandSupportType supportCreate() const { return cmdSupportNone; /**< @return CommandSupportType for creating */ } + virtual CommandSupportType supportCreateWithLabel() const { + return cmdSupportNone; /**< @return CommandSupportType for creating */ + } virtual CommandSupportType supportGrow() const { return cmdSupportNone; /**< @return CommandSupportType for growing */ } diff --git a/src/fs/udf.cpp b/src/fs/udf.cpp index 1861238..11ab07b 100644 --- a/src/fs/udf.cpp +++ b/src/fs/udf.cpp @@ -78,31 +78,9 @@ qint64 udf::maxLabelLength() const bool udf::create(Report& report, const QString& deviceNode) { - // mkudffs from udftools prior to 1.1 does not check for partition limits and crashes - if ( length() > MAX_UDF_BLOCKS ) { - report.line() << xi18nc("@info:status", "Partition is too large"); + int blkSize = blockSize(report, deviceNode); + if (blkSize == -1) return false; - } - if ( length() < MIN_UDF_BLOCKS ) { - report.line() << xi18nc("@info:status", "Partition is too small"); - return false; - } - - // mkudffs from udftools prior to 1.1 is not able to detect logical (sector) size - // and UDF block size must match logical sector size of underlying media - int fd = open(deviceNode.toLocal8Bit().data(), O_RDONLY); - if ( fd < 0 ) { - report.line() << xi18nc("@info:status", "Cannot open device node"); - return false; - } - int blksize; - int ret = ioctl(fd, BLKSSZGET, &blksize); - close(fd); - - if ( ret != 0 ) { - report.line() << xi18nc("@info:status", "Cannot read logical (sector) size of device node"); - return false; - } ExternalCommand cmd(report, QStringLiteral("mkudffs"), { QStringLiteral("--utf8"), @@ -110,7 +88,7 @@ bool udf::create(Report& report, const QString& deviceNode) // For now format as UDF revision 2.01 for hard disk media type QStringLiteral("--media-type=hd"), QStringLiteral("--udfrev=0x201"), - QStringLiteral("--blocksize=") + QString::number(blksize), + QStringLiteral("--blocksize=") + QString::number(blkSize), // TODO: Pass label as udf::create() parameter // QStringLiteral("--lvid=") + label, // QStringLiteral("--vid=") + shortlabel, @@ -118,4 +96,56 @@ bool udf::create(Report& report, const QString& deviceNode) }); return cmd.run(-1) && cmd.exitCode() == 0; } + +bool udf::createWithLabel(Report& report, const QString& deviceNode, const QString& label) +{ + int blkSize = blockSize(report, deviceNode); + if (blkSize == -1) + return false; + + ExternalCommand cmd(report, QStringLiteral("mkudffs"), { + QStringLiteral("--utf8"), + // TODO: Add GUI option for choosing different optical disks and UDF revision + // For now format as UDF revision 2.01 for hard disk media type + QStringLiteral("--media-type=hd"), + QStringLiteral("--udfrev=0x201"), + QStringLiteral("--blocksize=") + QString::number(blkSize), + // TODO: Pass label as udf::create() parameter + QStringLiteral("--lvid=") + label, + // QStringLiteral("--vid=") + shortlabel, + deviceNode + }); + return cmd.run(-1) && cmd.exitCode() == 0; +} + +int udf::blockSize(Report& report, const QString& deviceNode) +{ + // mkudffs from udftools prior to 1.1 does not check for partition limits and crashes + if ( length() > MAX_UDF_BLOCKS ) { + report.line() << xi18nc("@info:status", "Partition is too large"); + return -1; + } + if ( length() < MIN_UDF_BLOCKS ) { + report.line() << xi18nc("@info:status", "Partition is too small"); + return -1; + } + + // mkudffs from udftools prior to 1.1 is not able to detect logical (sector) size + // and UDF block size must match logical sector size of underlying media + int fd = open(deviceNode.toLocal8Bit().data(), O_RDONLY); + if ( fd < 0 ) { + report.line() << xi18nc("@info:status", "Cannot open device node"); + return -1; + } + int blksize; + int ret = ioctl(fd, BLKSSZGET, &blksize); + close(fd); + + if ( ret != 0 ) { + report.line() << xi18nc("@info:status", "Cannot read logical (sector) size of device node"); + return -1; + } + return blksize; +} + } diff --git a/src/fs/udf.h b/src/fs/udf.h index eeae9c1..2e2b770 100644 --- a/src/fs/udf.h +++ b/src/fs/udf.h @@ -43,6 +43,7 @@ public: void init() override; bool create(Report& report, const QString& deviceNode) override; + bool createWithLabel(Report& report, const QString& deviceNode, const QString& label) override; CommandSupportType supportGetLabel() const override { return cmdSupportCore; @@ -50,6 +51,9 @@ public: CommandSupportType supportCreate() const override { return m_Create; } + CommandSupportType supportCreateWithLabel() const override { + return m_Create; + } CommandSupportType supportMove() const override { return cmdSupportCore; } @@ -71,6 +75,9 @@ public: public: static CommandSupportType m_Create; + +private: + int blockSize(Report& report, const QString& deviceNode); }; } diff --git a/src/jobs/createfilesystemjob.cpp b/src/jobs/createfilesystemjob.cpp index 5daf76e..68f568e 100644 --- a/src/jobs/createfilesystemjob.cpp +++ b/src/jobs/createfilesystemjob.cpp @@ -35,10 +35,11 @@ /** Creates a new CreateFileSystemJob @param p the Partition the FileSystem to create is on */ -CreateFileSystemJob::CreateFileSystemJob(Device& d, Partition& p) : +CreateFileSystemJob::CreateFileSystemJob(Device& d, Partition& p, const QString& label) : Job(), m_Device(d), - m_Partition(p) + m_Partition(p), + m_Label(label) { } @@ -51,8 +52,13 @@ bool CreateFileSystemJob::run(Report& parent) if (partition().fileSystem().type() == FileSystem::Unformatted) return true; + bool createResult; if (partition().fileSystem().supportCreate() == FileSystem::cmdSupportFileSystem) { - if (partition().fileSystem().create(*report, partition().deviceNode())) { + if (partition().fileSystem().supportCreateWithLabel() == FileSystem::cmdSupportFileSystem) + createResult = partition().fileSystem().createWithLabel(*report, partition().deviceNode(), m_Label); + else + createResult = partition().fileSystem().create(*report, partition().deviceNode()); + if (createResult) { if (device().type() == Device::Disk_Device) { CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device().deviceNode()); diff --git a/src/jobs/createfilesystemjob.h b/src/jobs/createfilesystemjob.h index 4303602..2fc12e4 100644 --- a/src/jobs/createfilesystemjob.h +++ b/src/jobs/createfilesystemjob.h @@ -33,7 +33,7 @@ class QString; class CreateFileSystemJob : public Job { public: - CreateFileSystemJob(Device& d, Partition& p); + CreateFileSystemJob(Device& d, Partition& p, const QString& label = {}); public: bool run(Report& parent) override; @@ -57,6 +57,7 @@ protected: private: Device& m_Device; Partition& m_Partition; + const QString& m_Label; }; #endif diff --git a/src/ops/newoperation.cpp b/src/ops/newoperation.cpp index b11f559..7814b92 100644 --- a/src/ops/newoperation.cpp +++ b/src/ops/newoperation.cpp @@ -62,7 +62,7 @@ NewOperation::NewOperation(Device& d, Partition* p) : // label. The operation stack will merge these operations with this one here // and if the jobs don't exist things will break. - m_CreateFileSystemJob = new CreateFileSystemJob(targetDevice(), newPartition()); + m_CreateFileSystemJob = new CreateFileSystemJob(targetDevice(), newPartition(), fs.label()); addJob(createFileSystemJob()); if (fs.type() == FileSystem::Lvm2_PV) {