Merge branch 'kauth'

This commit is contained in:
Andrius Štikonas 2018-07-25 09:37:52 +00:00
commit 24d9d1bd73
176 changed files with 5217 additions and 3230 deletions

View File

@ -16,14 +16,22 @@
project(kpmcore)
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
set(CMAKE_USE_RELATIVE_PATHS OFF)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
set(QT_MIN_VERSION "5.7.0")
# Dependencies
set(QT_MIN_VERSION "5.10.0")
set(KF5_MIN_VERSION "5.25")
set(BLKID_MIN_VERSION "2.32")
# Qca-qt5 (tested with botan and ossl backends)
# Runtime
# smartmontools 6.7
set(VERSION_MAJOR "3")
set(VERSION_MINOR "3")
set(VERSION_MINOR "50")
set(VERSION_RELEASE "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE})
set(SOVERSION "8")
@ -32,7 +40,7 @@ add_definitions(-D'VERSION="${VERSION}"') #"
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(ECM 1.0.0 REQUIRED NO_MODULE)
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
include(KDEInstallDirs)
@ -41,7 +49,6 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
include(FeatureSummary)
include(GenerateExportHeader)
include(ECMSetupVersion)
include(ECMPackageConfigHelpers)
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h"
@ -56,12 +63,15 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
)
# Load the frameworks we need
find_package(KF5 REQUIRED
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED
Auth
I18n
CoreAddons
WidgetsAddons
)
find_package(Qca-qt5 REQUIRED)
# use sane compile flags
add_definitions(
-DQT_USE_QSTRINGBUILDER
@ -76,10 +86,10 @@ add_definitions(
)
kde_enable_exceptions()
find_package(PkgConfig REQUIRED)
pkg_check_modules(BLKID REQUIRED blkid>=2.30)
pkg_check_modules(LIBATASMART REQUIRED libatasmart)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
find_package(PkgConfig REQUIRED)
pkg_check_modules(BLKID REQUIRED blkid>=${BLKID_MIN_VERSION})
endif()
include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/)
@ -89,7 +99,7 @@ add_subdirectory(src)
set(INCLUDE_INSTALL_DIR "include/kpmcore/")
set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KPMcore")
ecm_configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KPMcoreConfig.cmake.in"
configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KPMcoreConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/KPMcoreConfig.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
PATH_VARS INCLUDE_INSTALL_DIR

12
INSTALL
View File

@ -4,24 +4,16 @@ Building and installing KDE Partition Manager Core Library from source
1. Dependencies
libparted: Either get it from http://www.gnu.org/software/parted/download.shtml
and build it yourself or, preferably, install your distribution's packages
(don't forget the dev-package).
libblkid: Part of the util-linux project available at
https://github.com/karelzak/util-linux
libatasmart: Available from http://0pointer.de/blog/projects/being-smart.html
util-linux 2.32: available at https://github.com/karelzak/util-linux
KDE Frameworks: The minimum required version is 5.0.
2. Configure
KPMcore is built with cmake. It is recommended to build out of tree:
After unpacking the source, create a separate build directory and run cmake there:
$ tar xfj kpmcore-x.y.z.tar.bz2
$ tar xf kpmcore-x.y.z.tar.xz
$ cd kpmcore-x.y.z
$ mkdir build
$ cd build

View File

@ -14,7 +14,7 @@ of storage devices on a system:
There are multiple backends so that KPMcore can support different
operating systems, although the only functional backend is the
one for Linux systems:
* libparted backend (Linux)
* sfdisk backend (Linux)
* null backend
## Using KPMcore

View File

@ -1,57 +0,0 @@
# Copyright (C) 2008,2010,2011 by Volker Lanz <vl@fidra.de>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include(CheckCSourceCompiles)
include(CheckFunctionExists)
if (LIBPARTED_INCLUDE_DIR AND LIBPARTED_LIBRARY)
# Already in cache, be silent
set(LIBPARTED_FIND_QUIETLY TRUE)
endif (LIBPARTED_INCLUDE_DIR AND LIBPARTED_LIBRARY)
FIND_PATH(LIBPARTED_INCLUDE_DIR parted.h PATH_SUFFIXES parted )
FIND_LIBRARY(LIBPARTED_LIBRARY NAMES parted)
FIND_LIBRARY(LIBPARTED_FS_RESIZE_LIBRARY NAMES parted-fs-resize)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPARTED DEFAULT_MSG LIBPARTED_LIBRARY LIBPARTED_INCLUDE_DIR)
if (LIBPARTED_FS_RESIZE_LIBRARY)
set(LIBPARTED_LIBS ${LIBPARTED_FS_RESIZE_LIBRARY} ${LIBPARTED_LIBRARY})
else (LIBPARTED_FS_RESIZE_LIBRARY)
set(LIBPARTED_LIBS ${LIBPARTED_LIBRARY})
endif (LIBPARTED_FS_RESIZE_LIBRARY)
# KDE adds -ansi to the C make flags, parted headers use GNU extensions, so
# undo that
unset(CMAKE_C_FLAGS)
set(CMAKE_REQUIRED_INCLUDES ${LIBPARTED_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${LIBPARTED_LIBS})
CHECK_FUNCTION_EXISTS("ped_file_system_clobber" LIBPARTED_FILESYSTEM_SUPPORT) # parted < 3.0
CHECK_FUNCTION_EXISTS("ped_file_system_resize" LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT) # parted != 3.0
MARK_AS_ADVANCED(LIBPARTED_LIBRARY LIBPARTED_INCLUDE_DIR LIBPARTED_FILESYSTEM_SUPPORT LIBPARTED_FS_RESIZE_LIBRARY LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT)

View File

@ -39,14 +39,17 @@ set(kpmcore_SRCS
ki18n_wrap_ui(kpmcore_SRCS ${gui_UIFILES})
add_library(kpmcore SHARED ${kpmcore_SRCS})
target_link_libraries( kpmcore
${UUID_LIBRARIES}
target_link_libraries( kpmcore PUBLIC
Qt5::Core
PRIVATE
${BLKID_LIBRARIES}
${LIBATASMART_LIBRARIES}
Qt5::DBus
Qt5::Gui
qca-qt5
KF5::I18n
KF5::CoreAddons
KF5::WidgetsAddons
KF5::Auth
)
install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS})

View File

@ -24,20 +24,18 @@
#include <QDebug>
class CoreBackend::CoreBackendPrivate
struct CoreBackendPrivate
{
public:
CoreBackendPrivate() {}
QString m_id, m_version;
};
CoreBackend::CoreBackend() :
d(new CoreBackendPrivate())
d(std::make_unique<CoreBackendPrivate>())
{
}
CoreBackend::~CoreBackend()
{
delete d;
}
void CoreBackend::emitProgress(int i)
@ -59,3 +57,23 @@ void CoreBackend::setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_pr
{
p.setMaxPrimaries(max_primaries);
}
QString CoreBackend::id()
{
return d->m_id;
}
QString CoreBackend::version()
{
return d->m_version;
}
void CoreBackend::setId(const QString& id)
{
d->m_id = id;
}
void CoreBackend::setVersion(const QString& version)
{
d->m_version = version;
}

View File

@ -23,11 +23,14 @@
#include "util/libpartitionmanagerexport.h"
#include "fs/filesystem.h"
#include <memory>
#include <QObject>
#include <QList>
class CoreBackendManager;
class CoreBackendDevice;
struct CoreBackendPrivate;
class Device;
class PartitionTable;
@ -68,17 +71,13 @@ public:
* Return the plugin's unique Id from JSON metadata
* @return the plugin's unique Id from JSON metadata
*/
QString id() {
return m_id;
}
QString id();
/**
* Return the plugin's version from JSON metadata
* @return the plugin's version from JSON metadata
*/
QString version() {
return m_version;
}
QString version();
/**
* Initialize the plugin's FileSystem support
@ -130,29 +129,23 @@ public:
/**
* Open a device for reading.
* @param deviceNode The path of the device that is to be opened (e.g. /dev/sda)
* @return a pointer to a CoreBackendDevice or nullptr if the open failed. If a pointer to
* an instance is returned, it's the caller's responsibility to delete the
* object.
* @return a pointer to a CoreBackendDevice or nullptr if the open failed.
*/
virtual CoreBackendDevice* openDevice(const Device& d) = 0;
virtual std::unique_ptr<CoreBackendDevice> openDevice(const Device& d) = 0;
/**
* Open a device in exclusive mode for writing.
* @param deviceNode The path of the device that is to be opened (e.g. /dev/sda)
* @return a pointer to a CoreBackendDevice or nullptr if the open failed. If a pointer to
* an instance is returned, it's the caller's responsibility to delete the
* object.
* @return a pointer to a CoreBackendDevice or nullptr if the open failed.
*/
virtual CoreBackendDevice* openDeviceExclusive(const Device& d) = 0;
virtual std::unique_ptr<CoreBackendDevice> openDeviceExclusive(const Device& d) = 0;
/**
* Close a CoreBackendDevice that has previously been opened.
* @param core_device Pointer to the CoreBackendDevice to be closed. Must not be nullptr.
* @return true if closing the CoreBackendDevice succeeded, otherwise false.
*
* This method does not delete the object.
*/
virtual bool closeDevice(CoreBackendDevice* core_device) = 0;
virtual bool closeDevice(std::unique_ptr<CoreBackendDevice> coreDevice) = 0;
/**
* Emit progress.
@ -176,18 +169,11 @@ protected:
static void setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_primaries);
private:
void setId(const QString& id) {
m_id = id;
}
void setVersion(const QString& version) {
m_version = version;
}
void setId(const QString& id);
void setVersion(const QString& version);
private:
QString m_id, m_version;
class CoreBackendPrivate;
CoreBackendPrivate* d;
std::unique_ptr<CoreBackendPrivate> d;
};
#endif

View File

@ -19,6 +19,7 @@
#define KPMCORE_COREBACKENDDEVICE_H
#include <memory>
#include <QString>
class CoreBackendPartition;
@ -81,7 +82,7 @@ public:
* @return a pointer to the CoreBackendPartitionTable for this device or nullptr in case
* of errors
*/
virtual CoreBackendPartitionTable* openPartitionTable() = 0;
virtual std::unique_ptr<CoreBackendPartitionTable> openPartitionTable() = 0;
/**
* Create a new partition table on this device.
@ -91,23 +92,6 @@ public:
*/
virtual bool createPartitionTable(Report& report, const PartitionTable& ptable) = 0;
/**
* Read data from an opened device into a buffer.
* @param buffer the buffer to write the read data to
* @param offset offset byte where to start reading on the device
* @param size the number of bytes to read
* @return true on success
*/
virtual bool readData(QByteArray& buffer, qint64 offset, qint64 size) = 0;
/**
* Write data from a buffer to an exclusively opened device.
* @param buffer the buffer with the data
* @param offset offset byte where to start writing to the device
* @return true on success
*/
virtual bool writeData(QByteArray& buffer, qint64 offset) = 0;
protected:
void setExclusive(bool b) {
m_Exclusive = b;

View File

@ -1,7 +1,7 @@
/*************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2015 by Teo Mrnjavac <teo@kde.org> *
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
* Copyright (C) 2016-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -20,8 +20,8 @@
#include "backend/corebackendmanager.h"
#include "backend/corebackend.h"
#include <QCoreApplication>
#include <QDebug>
#include <QStringList>
#include <QString>
#include <QVector>
@ -30,8 +30,17 @@
#include <KPluginLoader>
#include <KPluginMetaData>
struct CoreBackendManagerPrivate
{
CoreBackend *m_Backend;
};
CoreBackendManager::CoreBackendManager() :
m_Backend(nullptr)
d(std::make_unique<CoreBackendManagerPrivate>())
{
}
CoreBackendManager::~CoreBackendManager()
{
}
@ -45,6 +54,11 @@ CoreBackendManager* CoreBackendManager::self()
return instance;
}
CoreBackend* CoreBackendManager::backend()
{
return d->m_Backend;
}
QVector<KPluginMetaData> CoreBackendManager::list() const
{
auto filter = [&](const KPluginMetaData &metaData) {
@ -66,7 +80,7 @@ bool CoreBackendManager::load(const QString& name)
KPluginFactory* factory = loader.factory();
if (factory != nullptr) {
m_Backend = factory->create<CoreBackend>(nullptr);
d->m_Backend = factory->create<CoreBackend>(nullptr);
QString id = loader.metaData().toVariantMap().value(QStringLiteral("MetaData"))
.toMap().value(QStringLiteral("KPlugin")).toMap().value(QStringLiteral("Id")).toString();
@ -78,6 +92,7 @@ bool CoreBackendManager::load(const QString& name)
backend()->setId(id);
backend()->setVersion(version);
qDebug() << "Loaded backend plugin: " << backend()->id();
return true;
}
@ -87,6 +102,4 @@ bool CoreBackendManager::load(const QString& name)
void CoreBackendManager::unload()
{
delete m_Backend;
m_Backend = nullptr;
}

View File

@ -1,5 +1,6 @@
/*************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -15,18 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_COREBACKENDMANAGER_H)
#ifndef KPMCORE_COREBACKENDMANAGER_H
#define KPMCORE_COREBACKENDMANAGER_H
#include "util/libpartitionmanagerexport.h"
#include <memory>
#include <QVector>
class QString;
class QStringList;
class KPluginMetaData;
class CoreBackend;
struct CoreBackendManagerPrivate;
/**
* The backend manager class.
@ -37,8 +40,8 @@ class CoreBackend;
*/
class LIBKPMCORE_EXPORT CoreBackendManager
{
private:
CoreBackendManager();
~CoreBackendManager();
public:
/**
@ -50,7 +53,7 @@ public:
* @return the name of the default backend plugin
*/
static QString defaultBackendName() {
return QStringLiteral("pmlibpartedbackendplugin");
return QStringLiteral("pmsfdiskbackendplugin");
}
/**
@ -73,12 +76,10 @@ public:
/**
* @return a pointer to the currently loaded backend
*/
CoreBackend* backend() {
return m_Backend;
}
CoreBackend* backend();
private:
CoreBackend* m_Backend;
std::unique_ptr<CoreBackendManagerPrivate> d;
};
#endif

View File

@ -1,3 +1,5 @@
include(core/raid/CMakeLists.txt)
set(CORE_SRC
core/copysource.cpp
core/copysourcedevice.cpp
@ -20,7 +22,11 @@ set(CORE_SRC
core/partitiontable.cpp
core/smartstatus.cpp
core/smartattribute.cpp
core/smartparser.cpp
core/smartattributeparseddata.cpp
core/smartdiskinformation.cpp
core/volumemanagerdevice.cpp
${RAID_SRC}
)
set(CORE_LIB_HDRS
@ -39,5 +45,5 @@ set(CORE_LIB_HDRS
core/smartattribute.h
core/smartstatus.h
core/volumemanagerdevice.h
${RAID_LIB_HDRS}
)

View File

@ -22,6 +22,7 @@
#include <QtGlobal>
class CopyTarget;
class QString;
/** Base class for something to copy from.
@ -41,14 +42,12 @@ protected:
public:
virtual bool open() = 0;
virtual bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) = 0;
virtual QString path() const = 0;
virtual qint64 length() const = 0;
virtual bool overlaps(const CopyTarget& target) const = 0;
virtual qint64 firstByte() const = 0;
virtual qint64 lastByte() const = 0;
private:
};
#endif

View File

@ -20,7 +20,6 @@
#include "backend/corebackend.h"
#include "backend/corebackendmanager.h"
#include "backend/corebackenddevice.h"
#include "core/copytarget.h"
#include "core/copytargetdevice.h"
@ -40,12 +39,6 @@ CopySourceDevice::CopySourceDevice(Device& d, qint64 firstbyte, qint64 lastbyte)
{
}
/** Destructs a CopySourceDevice */
CopySourceDevice::~CopySourceDevice()
{
delete m_BackendDevice;
}
/** Opens the Device
@return true if the Device could be successfully opened
*/
@ -63,22 +56,6 @@ qint64 CopySourceDevice::length() const
return lastByte() - firstByte() + 1;
}
/** Reads a given number of bytes from the Device into the given buffer.
Note that @p readOffset must be greater or equal than zero.
@param buffer the buffer to store the read bytes in
@param readOffset the offset to begin reading
@param size the number of bytes to read
@return true if successful
*/
bool CopySourceDevice::readData(QByteArray& buffer, qint64 readOffset, qint64 size)
{
Q_ASSERT(readOffset >= 0);
return m_BackendDevice->readData(buffer, readOffset, size);
}
/** Checks if this CopySourceDevice overlaps with the given CopyTarget
@param target the CopyTarget to check overlapping with
@return true if overlaps
@ -103,3 +80,8 @@ bool CopySourceDevice::overlaps(const CopyTarget& target) const
return false;
}
QString CopySourceDevice::path() const
{
return m_Device.deviceNode();
}

View File

@ -19,14 +19,18 @@
#define KPMCORE_COPYSOURCEDEVICE_H
#include "backend/corebackenddevice.h"
#include "core/copysource.h"
#include "util/libpartitionmanagerexport.h"
#include <memory>
#include <QtGlobal>
class Device;
class CopyTarget;
class CoreBackendDevice;
class QString;
/** A Device to copy from.
@ -40,11 +44,9 @@ class CopySourceDevice : public CopySource
public:
CopySourceDevice(Device& d, qint64 firstbyte, qint64 lastbyte);
~CopySourceDevice();
public:
bool open() override;
bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override;
qint64 length() const override;
bool overlaps(const CopyTarget& target) const override;
@ -62,12 +64,13 @@ public:
return m_Device; /**< @return Device to copy from */
}
QString path() const override;
protected:
Device& m_Device;
const qint64 m_FirstByte;
const qint64 m_LastByte;
CoreBackendDevice* m_BackendDevice
;
std::unique_ptr<CoreBackendDevice> m_BackendDevice;
};
#endif

View File

@ -45,18 +45,3 @@ qint64 CopySourceFile::length() const
{
return QFileInfo(file()).size();
}
/** Reads the given number of bytes from the file into the given buffer.
@param buffer buffer to store the bytes read in
@param readOffset offset where to begin reading
@param size the number of bytes to read
@return true on success
*/
bool CopySourceFile::readData(QByteArray& buffer, qint64 readOffset, qint64 size)
{
if (!file().seek(readOffset))
return false;
buffer = file().read(size);
return !buffer.isEmpty();
}

View File

@ -40,7 +40,6 @@ public:
public:
bool open() override;
bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override;
qint64 length() const override;
bool overlaps(const CopyTarget&) const override {
@ -52,6 +51,9 @@ public:
qint64 lastByte() const override {
return length(); /**< @return equal to length for file. @see length() */
}
QString path() const override {
return m_File.fileName();
}
protected:
QFile& file() {

View File

@ -43,17 +43,3 @@ qint64 CopySourceShred::length() const
{
return size();
}
/** Reads the given number of bytes from the source into the given buffer.
@param buffer buffer to store the data read in
@param readOffset offset where to begin reading (unused)
@param size the number of bytes to read
@return true on success
*/
bool CopySourceShred::readData(QByteArray& buffer, qint64 readOffset, qint64 size)
{
Q_UNUSED(readOffset);
buffer = sourceFile().read(size);
return !buffer.isEmpty();
}

View File

@ -24,6 +24,7 @@
#include <QFile>
class CopyTarget;
class QString;
/** A source for securely overwriting a partition (shredding).
@ -38,7 +39,6 @@ public:
public:
bool open() override;
bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override;
qint64 length() const override;
bool overlaps(const CopyTarget&) const override {
@ -50,6 +50,9 @@ public:
qint64 lastByte() const override {
return length(); /**< @return equal to length for shred source. @see length() */
}
QString path() const override {
return m_SourceFile.fileName();
}
protected:
QFile& sourceFile() {

View File

@ -21,6 +21,7 @@
#include <QtGlobal>
class QString;
/** Base class for something to copy to.
@ -40,10 +41,9 @@ protected:
public:
virtual bool open() = 0;
virtual bool writeData(QByteArray& buffer, qint64 writeOffset) = 0;
virtual qint64 firstByte() const = 0;
virtual qint64 lastByte() const = 0;
virtual QString path() const = 0;
qint64 bytesWritten() const {
return m_BytesWritten;
}

View File

@ -19,11 +19,9 @@
#include "backend/corebackend.h"
#include "backend/corebackendmanager.h"
#include "backend/corebackenddevice.h"
#include "core/device.h"
/** Constructs a device to copy to.
@param d the Device to copy to
@param firstbyte the first byte on the Device to write to
@ -38,12 +36,6 @@ CopyTargetDevice::CopyTargetDevice(Device& d, qint64 firstbyte, qint64 lastbyte)
{
}
/** Destructs a CopyTargetDevice */
CopyTargetDevice::~CopyTargetDevice()
{
delete m_BackendDevice;
}
/** Opens a CopyTargetDevice for writing to.
@return true on success
*/
@ -53,21 +45,7 @@ bool CopyTargetDevice::open()
return m_BackendDevice != nullptr;
}
/** Writes the given number of bytes to the Device.
Note that @p writeOffset must be greater or equal than zero.
@param buffer the data to write
@param writeOffset where to start writing on the Device
@return true on success
*/
bool CopyTargetDevice::writeData(QByteArray& buffer, qint64 writeOffset)
QString CopyTargetDevice::path() const
{
Q_ASSERT(writeOffset >= 0);
bool rval = m_BackendDevice->writeData(buffer, writeOffset);
if (rval)
setBytesWritten(bytesWritten() + buffer.size());
return rval;
return m_Device.deviceNode();
}

View File

@ -19,9 +19,12 @@
#define KPMCORE_COPYTARGETDEVICE_H
#include "backend/corebackenddevice.h"
#include "core/copytarget.h"
#include "util/libpartitionmanagerexport.h"
#include <memory>
#include <QtGlobal>
class Device;
@ -42,11 +45,9 @@ class CopyTargetDevice : public CopyTarget
public:
CopyTargetDevice(Device& d, qint64 firstbyte, qint64 lastbyte);
~CopyTargetDevice();
public:
bool open() override;
bool writeData(QByteArray& buffer, qint64 writeOffset) override;
qint64 firstByte() const override {
return m_FirstByte; /**< @return the first byte to write to */
}
@ -60,10 +61,11 @@ public:
const Device& device() const {
return m_Device; /**< @return the Device to write to */
}
QString path() const override;
protected:
Device& m_Device;
CoreBackendDevice* m_BackendDevice;
std::unique_ptr<CoreBackendDevice> m_BackendDevice;
const qint64 m_FirstByte;
const qint64 m_LastByte;
};

View File

@ -33,21 +33,3 @@ bool CopyTargetFile::open()
{
return file().open(QIODevice::WriteOnly | QIODevice::Truncate);
}
/** Writes the given number of bytes from the given buffer to the file.
@param buffer the data to write
@param writeOffset where in the file to start writing
@return true on success
*/
bool CopyTargetFile::writeData(QByteArray& buffer, qint64 writeOffset)
{
if (!file().seek(writeOffset))
return false;
bool rval = file().write(buffer) == buffer.size();
if (rval)
setBytesWritten(bytesWritten() + buffer.size());
return rval;
}

View File

@ -40,7 +40,6 @@ public:
public:
bool open() override;
bool writeData(QByteArray& buffer, qint64 writeOffset) override;
qint64 firstByte() const override {
return 0; /**< @return always 0 for a file */
@ -49,6 +48,10 @@ public:
return bytesWritten(); /**< @return the number of bytes written so far */
}
QString path() const override {
return m_File.fileName();
}
protected:
QFile& file() {
return m_File;

View File

@ -1,6 +1,6 @@
/*************************************************************************
* Copyright (C) 2008 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
* Copyright (C) 2016-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -17,6 +17,7 @@
*************************************************************************/
#include "core/device.h"
#include "core/device_p.h"
#include "core/partitiontable.h"
#include "core/smartstatus.h"
@ -28,22 +29,24 @@
@param name the Device's name, usually some string defined by the manufacturer
@param deviceNode the Device's node, for example "/dev/sda"
*/
Device::Device(const QString& name,
Device::Device(std::shared_ptr<DevicePrivate> d_ptr,
const QString& name,
const QString& deviceNode,
const qint64 logicalSize,
const qint64 totalLogical,
const qint64 logicalSectorSize,
const qint64 totalLogicalSectors,
const QString& iconName,
Device::Type type)
: QObject()
, m_Name(name.length() > 0 ? name : i18n("Unknown Device"))
, m_DeviceNode(deviceNode)
, m_LogicalSize(logicalSize)
, m_TotalLogical(totalLogical)
, m_PartitionTable(nullptr)
, m_IconName(iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName)
, m_SmartStatus(type == Device::Disk_Device ? new SmartStatus(deviceNode) : nullptr)
, m_Type(type)
, d(d_ptr)
{
d->m_Name = name.length() > 0 ? name : i18n("Unknown Device");
d->m_DeviceNode = deviceNode;
d->m_LogicalSectorSize = logicalSectorSize;
d->m_TotalLogical = totalLogicalSectors;
d->m_PartitionTable = nullptr;
d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName;
d->m_SmartStatus = type == Device::Type::Disk_Device ? std::make_shared<SmartStatus>(deviceNode) : nullptr;
d->m_Type = type;
}
/** Copy constructor for Device.
@ -51,30 +54,31 @@ Device::Device(const QString& name,
*/
Device::Device(const Device& other)
: QObject()
, m_Name(other.m_Name)
, m_DeviceNode(other.m_DeviceNode)
, m_LogicalSize(other.m_LogicalSize)
, m_TotalLogical(other.m_TotalLogical)
, m_PartitionTable(nullptr)
, m_IconName(other.m_IconName)
, m_SmartStatus(nullptr)
, m_Type(other.m_Type)
, d(std::make_shared<DevicePrivate>())
{
if (other.m_PartitionTable)
m_PartitionTable = new PartitionTable(*other.m_PartitionTable);
if (other.m_SmartStatus)
m_SmartStatus = new SmartStatus(*other.m_SmartStatus);
d->m_Name = other.d->m_Name;
d->m_DeviceNode = other.d->m_DeviceNode;
d->m_LogicalSectorSize = other.d->m_LogicalSectorSize;
d->m_TotalLogical = other.d->m_TotalLogical;
d->m_PartitionTable = nullptr;
d->m_IconName = other.d->m_IconName;
d->m_SmartStatus = nullptr;
d->m_Type = other.d->m_Type;
d->m_SmartStatus = other.d->m_SmartStatus;
if (other.d->m_PartitionTable)
d->m_PartitionTable = new PartitionTable(*other.d->m_PartitionTable);
}
/** Destructs a Device. */
Device::~Device()
{
delete m_PartitionTable;
delete d->m_PartitionTable;
}
bool Device::operator==(const Device& other) const
{
return m_DeviceNode == other.m_DeviceNode;
return d->m_DeviceNode == other.d->m_DeviceNode;
}
bool Device::operator!=(const Device& other) const
@ -86,3 +90,68 @@ QString Device::prettyName() const
{
return xi18nc("@item:inlistbox Device name Capacity (device node)", "%1 %2 (%3)", name(), Capacity::formatByteSize(capacity()), deviceNode());
}
QString& Device::name()
{
return d->m_Name;
}
const QString& Device::name() const
{
return d->m_Name;
}
const QString& Device::deviceNode() const
{
return d->m_DeviceNode;
}
qint64 Device::logicalSize() const
{
return d->m_LogicalSectorSize;
}
qint64 Device::totalLogical() const
{
return d->m_TotalLogical;
}
PartitionTable* Device::partitionTable()
{
return d->m_PartitionTable;
}
const PartitionTable* Device::partitionTable() const
{
return d->m_PartitionTable;
}
void Device::setPartitionTable(PartitionTable* ptable)
{
d->m_PartitionTable = ptable;
}
const QString& Device::iconName() const
{
return d->m_IconName;
}
void Device::setIconName(const QString& name)
{
d->m_IconName = name;
}
SmartStatus& Device::smartStatus()
{
return *(d->m_SmartStatus);
}
const SmartStatus& Device::smartStatus() const
{
return *(d->m_SmartStatus);
}
Device::Type Device::type() const
{
return d->m_Type;
}

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_DEVICE_H)
#ifndef KPMCORE_DEVICE_H
#define KPMCORE_DEVICE_H
#include "util/libpartitionmanagerexport.h"
@ -24,10 +23,13 @@
#include <QString>
#include <QObject>
#include <memory>
class PartitionTable;
class CreatePartitionTableOperation;
class CoreBackend;
class SmartStatus;
class DevicePrivate;
/** A device description.
@ -48,96 +50,66 @@ class LIBKPMCORE_EXPORT Device : public QObject
friend class CoreBackend;
public:
enum Type {
Disk_Device = 0,
LVM_Device = 1, /* VG */
RAID_Device = 2, /* software RAID device */
Unknown_Device = 4
enum class Type {
Unknown_Device,
Disk_Device,
LVM_Device, /* VG */
SoftwareRAID_Device, /* software RAID device, i.e. mdraid */
FakeRAID_Device, /* fake RAID device, i.e. dmraid */
};
protected:
explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Disk_Device);
explicit Device(std::shared_ptr<DevicePrivate> d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Type::Disk_Device);
public:
explicit Device(const Device& other);
virtual ~Device();
public:
virtual bool operator==(const Device& other) const;
virtual bool operator!=(const Device& other) const;
virtual QString& name() {
return m_Name; /**< @return the Device's name, usually some manufacturer string */
}
/**< @return the Device's name, usually some manufacturer string */
virtual QString& name();
virtual const QString& name() const;
virtual const QString& name() const {
return m_Name; /**< @return the Device's name, usually some manufacturer string */
}
/**< @return the Device's node, for example "/dev/sda" */
virtual const QString& deviceNode() const;
virtual const QString& deviceNode() const {
return m_DeviceNode; /**< @return the Device's node, for example "/dev/sda" */
}
/**< @return the logical sector size the Device uses (would be extent size for e.g. LVM devices) */
virtual qint64 logicalSize() const;
virtual PartitionTable* partitionTable() {
return m_PartitionTable; /**< @return the Device's PartitionTable */
}
/**< @return the total number of logical sectors on the device */
virtual qint64 totalLogical() const;
virtual const PartitionTable* partitionTable() const {
return m_PartitionTable; /**< @return the Device's PartitionTable */
}
virtual qint64 capacity() const { /**< @return the Device's capacity in bytes */
return logicalSize() * totalLogical();
}
virtual void setIconName(const QString& name) {
m_IconName = name;
}
virtual const QString& iconName() const {
return m_IconName; /**< @return suggested icon name for this Device */
}
virtual SmartStatus& smartStatus() {
return *m_SmartStatus;
}
virtual const SmartStatus& smartStatus() const {
return *m_SmartStatus;
}
/**< @return the Device's PartitionTable */
virtual PartitionTable* partitionTable();
virtual const PartitionTable* partitionTable() const;
/**
* Change the description of the partition table for different one.
* The device itself is not changed; use CreatePartitionTableOperation
* for that. The Device instance becomes the owner of @p ptable .
*/
virtual void setPartitionTable(PartitionTable* ptable) {
m_PartitionTable = ptable;
virtual void setPartitionTable(PartitionTable* ptable);
virtual qint64 capacity() const { /**< @return the Device's capacity in bytes */
return logicalSize() * totalLogical();
}
virtual qint64 logicalSize() const {
return m_LogicalSize;
}
/**< @return suggested icon name for this Device */
virtual const QString& iconName() const;
virtual qint64 totalLogical() const {
return m_TotalLogical;
}
/**< @param name set the new Icon for this Device */
virtual void setIconName(const QString& name);
virtual Device::Type type() const {
return m_Type;
}
virtual SmartStatus& smartStatus();
virtual const SmartStatus& smartStatus() const;
virtual Device::Type type() const;
virtual QString prettyName() const;
protected:
QString m_Name;
QString m_DeviceNode;
qint64 m_LogicalSize;
qint64 m_TotalLogical;
PartitionTable* m_PartitionTable;
QString m_IconName;
SmartStatus* m_SmartStatus;
Device::Type m_Type;
std::shared_ptr<DevicePrivate> d;
};
#endif

43
src/core/device_p.h Normal file
View File

@ -0,0 +1,43 @@
/*************************************************************************
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#ifndef KPMCORE_DEVICE_P_H
#define KPMCORE_DEVICE_P_H
#include "core/device.h"
#include <QString>
#include <memory>
class PartitionTable;
class SmartStatus;
class DevicePrivate
{
public:
QString m_Name;
QString m_DeviceNode;
qint64 m_LogicalSectorSize;
qint64 m_TotalLogical;
PartitionTable* m_PartitionTable;
QString m_IconName;
std::shared_ptr<SmartStatus> m_SmartStatus;
Device::Type m_Type;
};
#endif

View File

@ -1,6 +1,6 @@
/*************************************************************************
* Copyright (C) 2008 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
* Copyright (C) 2016-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -17,6 +17,7 @@
*************************************************************************/
#include "core/diskdevice.h"
#include "core/device_p.h"
#include "core/partitiontable.h"
#include "core/smartstatus.h"
@ -39,14 +40,25 @@
#define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */
#endif
#define d_ptr std::static_pointer_cast<DiskDevicePrivate>(d)
class DiskDevicePrivate : public DevicePrivate
{
public:
qint32 m_Heads;
qint32 m_SectorsPerTrack;
qint32 m_Cylinders;
qint64 m_LogicalSectorSize;
qint64 m_PhysicalSectorSize;
};
static qint64 getPhysicalSectorSize(const QString& device_node)
{
/*
* possible ways of getting the physical sector size for a drive:
* - ioctl(BLKPBSZGET) -- supported with Linux 2.6.32 and later
* - /sys/block/sda/queue/physical_block_size
* - libblkid from util-linux-ng 2.17 or later
* TODO: implement the blkid method
* - libblkid from util-linux 2.17 or later (not implemented)
*/
#if defined(BLKPBSZGET)
@ -87,11 +99,46 @@ DiskDevice::DiskDevice(const QString& name,
qint32 cylinders,
qint64 sectorSize,
const QString& iconName)
: Device(name, deviceNode, sectorSize, (static_cast<qint64>(heads) * cylinders * numSectors), iconName, Device::Disk_Device)
, m_Heads(heads)
, m_SectorsPerTrack(numSectors)
, m_Cylinders(cylinders)
, m_LogicalSectorSize(sectorSize)
, m_PhysicalSectorSize(getPhysicalSectorSize(deviceNode))
: Device(std::make_shared<DiskDevicePrivate>(), name, deviceNode, sectorSize, (static_cast<qint64>(heads) * cylinders * numSectors), iconName, Device::Type::Disk_Device)
{
d_ptr->m_Heads = heads;
d_ptr->m_SectorsPerTrack = numSectors;
d_ptr->m_Cylinders = cylinders;
d_ptr->m_LogicalSectorSize = sectorSize;
d_ptr->m_PhysicalSectorSize = getPhysicalSectorSize(deviceNode);
}
qint32 DiskDevice::heads() const
{
return d_ptr->m_Heads;
}
qint32 DiskDevice::cylinders() const
{
return d_ptr->m_Cylinders;
}
qint32 DiskDevice::sectorsPerTrack() const
{
return d_ptr->m_SectorsPerTrack;
}
qint64 DiskDevice::physicalSectorSize() const
{
return d_ptr->m_PhysicalSectorSize;
}
qint64 DiskDevice::logicalSectorSize() const
{
return d_ptr->m_LogicalSectorSize;
}
qint64 DiskDevice::totalSectors() const
{
return static_cast<qint64>(d_ptr->m_Heads) * d_ptr->m_Cylinders * d_ptr->m_SectorsPerTrack;
}
qint64 DiskDevice::cylinderSize() const
{
return static_cast<qint64>(d_ptr->m_Heads) * d_ptr->m_SectorsPerTrack;
}

View File

@ -1,5 +1,6 @@
/*************************************************************************
* Copyright (C) 2008 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -15,13 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_DISKDEVICE_H)
#ifndef KPMCORE_DISKDEVICE_H
#define KPMCORE_DISKDEVICE_H
#include "util/libpartitionmanagerexport.h"
#include "core/device.h"
#include <memory>
#include <QString>
#include <QObject>
#include <QtGlobal>
@ -30,6 +32,7 @@ class PartitionTable;
class CreatePartitionTableOperation;
class CoreBackend;
class SmartStatus;
class DiskDevicePrivate;
/** A disk device.
@ -40,6 +43,7 @@ class SmartStatus;
@see PartitionTable, Partition
@author Volker Lanz <vl@fidra.de>
*/
class LIBKPMCORE_EXPORT DiskDevice : public Device
{
Q_DISABLE_COPY(DiskDevice)
@ -51,34 +55,42 @@ public:
DiskDevice(const QString& name, const QString& deviceNode, qint32 heads, qint32 numSectors, qint32 cylinders, qint64 sectorSize, const QString& iconName = QString());
public:
qint32 heads() const {
return m_Heads; /**< @return the number of heads on the Device in CHS notation */
}
qint32 cylinders() const {
return m_Cylinders; /**< @return the number of cylinders on the Device in CHS notation */
}
qint32 sectorsPerTrack() const {
return m_SectorsPerTrack; /**< @return the number of sectors on the Device in CHS notation */
}
qint64 physicalSectorSize() const {
return m_PhysicalSectorSize; /**< @return the physical sector size the Device uses or -1 if unknown */
}
qint64 logicalSectorSize() const {
return m_LogicalSectorSize; /**< @return the logical sector size the Device uses */
}
qint64 totalSectors() const {
return static_cast<qint64>(heads()) * cylinders() * sectorsPerTrack(); /**< @return the total number of sectors on the device */
}
qint64 cylinderSize() const {
return static_cast<qint64>(heads()) * sectorsPerTrack(); /**< @return the size of a cylinder on this Device in sectors */
}
/**
* @return the number of heads on the Device in CHS notation
*/
[[deprecated]]
qint32 heads() const;
private:
qint32 m_Heads;
qint32 m_SectorsPerTrack;
qint32 m_Cylinders;
qint64 m_LogicalSectorSize;
qint64 m_PhysicalSectorSize;
/**
* @return the number of cylinders on the Device in CHS notation
*/
[[deprecated]]
qint32 cylinders() const;
/**
* @return the number of sectors on the Device in CHS notation
*/
qint32 sectorsPerTrack() const;
/**
* @return the physical sector size the Device uses or -1 if unknown
*/
qint64 physicalSectorSize() const;
/**
* @return the logical sector size the Device uses
*/
qint64 logicalSectorSize() const;
/**
* @return the total number of sectors on the device
*/
qint64 totalSectors() const;
/**
* @return the size of a cylinder on this Device in sectors
*/
qint64 cylinderSize() const;
};
#endif

View File

@ -18,38 +18,47 @@
*************************************************************************/
#include "core/fstab.h"
#include "util/externalcommand.h"
#include <blkid/blkid.h>
#if defined(Q_OS_LINUX)
#include <blkid/blkid.h>
#endif
#include <QChar>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QRegularExpression>
#include <QTemporaryFile>
#include <QTextStream>
static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode);
static QString findBlkIdDevice(const QString& token, const QString& value);
static void parseFsSpec(const QString& m_fsSpec, FstabEntry::Type& m_entryType, QString& m_deviceNode);
static QString findBlkIdDevice(const char *token, const QString& value);
FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment)
: m_fsSpec(fsSpec)
, m_mountPoint(mountPoint)
, m_type(type)
, m_dumpFreq(dumpFreq)
, m_passNumber(passNumber)
, m_comment(comment)
struct FstabEntryPrivate
{
m_options = options.split(QLatin1Char(','));
parseFsSpec(m_fsSpec, m_entryType, m_deviceNode);
}
QString m_fsSpec;
QString m_deviceNode;
QString m_mountPoint;
QString m_type;
QStringList m_options;
int m_dumpFreq;
int m_passNumber;
QString m_comment;
FstabEntry::Type m_entryType;
};
/**
@param s the new value for the fs_spec field of fstab entry
*/
void FstabEntry::setFsSpec(const QString& s)
FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) :
d(std::make_unique<FstabEntryPrivate>())
{
m_fsSpec = s;
parseFsSpec(m_fsSpec, m_entryType, m_deviceNode);
d->m_fsSpec = fsSpec;
d->m_mountPoint = mountPoint;
d->m_type = type;
d->m_dumpFreq = dumpFreq;
d->m_passNumber = passNumber;
d->m_comment = comment;
d->m_options = options.split(QLatin1Char(','));
parseFsSpec(d->m_fsSpec, d->m_entryType, d->m_deviceNode);
}
FstabEntryList readFstabEntries( const QString& fstabPath )
@ -63,7 +72,7 @@ FstabEntryList readFstabEntries( const QString& fstabPath )
{
QString line = rawLine.trimmed();
if ( line.startsWith( QLatin1Char('#') ) || line.isEmpty()) {
fstabEntries.append( { {}, {}, {}, {}, {}, {}, line } );
fstabEntries.push_back( { {}, {}, {}, {}, {}, {}, line } );
continue;
}
@ -80,27 +89,98 @@ FstabEntryList readFstabEntries( const QString& fstabPath )
// (#) comment (optional).
switch (splitLine.length()) {
case 4:
fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3) } );
fstabEntries.push_back( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3) } );
break;
case 5:
fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt() } );
fstabEntries.push_back( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt() } );
break;
case 6:
fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt(), splitLine.at(5).toInt(), comment.isEmpty() ? QString() : QLatin1Char('#') + comment } );
fstabEntries.push_back( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt(), splitLine.at(5).toInt(), comment.isEmpty() ? QString() : QLatin1Char('#') + comment } );
break;
default:
fstabEntries.append( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } );
fstabEntries.push_back( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } );
}
}
fstabFile.close();
if (fstabEntries.last().entryType() == comment && fstabEntries.last().comment().isEmpty())
fstabEntries.removeLast();
if (fstabEntries.back().entryType() == FstabEntry::Type::comment && fstabEntries.back().comment().isEmpty())
fstabEntries.pop_back();
}
return fstabEntries;
}
void FstabEntry::setFsSpec(const QString& s)
{
d->m_fsSpec = s;
parseFsSpec(d->m_fsSpec, d->m_entryType, d->m_deviceNode);
}
const QString& FstabEntry::fsSpec() const
{
return d->m_fsSpec;
}
const QString& FstabEntry::deviceNode() const
{
return d->m_deviceNode;
}
const QString& FstabEntry::mountPoint() const
{
return d->m_mountPoint;
}
const QString& FstabEntry::type() const
{
return d->m_type;
}
const QStringList& FstabEntry::options() const
{
return d->m_options;
}
int FstabEntry::dumpFreq() const
{
return d->m_dumpFreq;
}
int FstabEntry::passNumber() const
{
return d->m_passNumber;
}
const QString& FstabEntry::comment() const
{
return d->m_comment;
}
FstabEntry::Type FstabEntry::entryType() const
{
return d->m_entryType;
}
void FstabEntry::setMountPoint(const QString& s)
{
d->m_mountPoint = s;
}
void FstabEntry::setOptions(const QStringList& s)
{
d->m_options = s;
}
void FstabEntry::setDumpFreq(int s)
{
d->m_dumpFreq = s;
}
void FstabEntry::setPassNumber(int s)
{
d->m_passNumber = s;
}
QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath)
{
QStringList mountPoints;
@ -113,40 +193,37 @@ QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabP
return mountPoints;
}
static QString findBlkIdDevice(const QString& token, const QString& value)
static QString findBlkIdDevice(const char *token, const QString& value)
{
blkid_cache cache;
QString rval;
if (blkid_get_cache(&cache, nullptr) == 0) {
if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), &cache)) {
rval = QString::fromLocal8Bit(c);
free(c);
}
blkid_put_cache(cache);
#if defined(Q_OS_LINUX)
if (char* c = blkid_evaluate_tag(token, value.toLocal8Bit().constData(), nullptr)) {
rval = QString::fromLocal8Bit(c);
free(c);
}
#endif
return rval;
}
static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode)
static void parseFsSpec(const QString& m_fsSpec, FstabEntry::Type& m_entryType, QString& m_deviceNode)
{
m_entryType = FstabEntryType::comment;
m_entryType = FstabEntry::Type::comment;
if (m_fsSpec.startsWith(QStringLiteral("UUID="))) {
m_entryType = FstabEntryType::uuid;
m_deviceNode = findBlkIdDevice(QStringLiteral("UUID"), QString(m_fsSpec).remove(QStringLiteral("UUID=")));
m_entryType = FstabEntry::Type::uuid;
m_deviceNode = findBlkIdDevice("UUID", QString(m_fsSpec).remove(QStringLiteral("UUID=")));
} else if (m_fsSpec.startsWith(QStringLiteral("LABEL="))) {
m_entryType = FstabEntryType::label;
m_deviceNode = findBlkIdDevice(QStringLiteral("LABEL"), QString(m_fsSpec).remove(QStringLiteral("LABEL=")));
m_entryType = FstabEntry::Type::label;
m_deviceNode = findBlkIdDevice("LABEL", QString(m_fsSpec).remove(QStringLiteral("LABEL=")));
} else if (m_fsSpec.startsWith(QStringLiteral("PARTUUID="))) {
m_entryType = FstabEntryType::uuid;
m_deviceNode = findBlkIdDevice(QStringLiteral("PARTUUID"), QString(m_fsSpec).remove(QStringLiteral("PARTUUID=")));
m_entryType = FstabEntry::Type::uuid;
m_deviceNode = findBlkIdDevice("PARTUUID", QString(m_fsSpec).remove(QStringLiteral("PARTUUID=")));
} else if (m_fsSpec.startsWith(QStringLiteral("PARTLABEL="))) {
m_entryType = FstabEntryType::label;
m_deviceNode = findBlkIdDevice(QStringLiteral("PARTLABEL"), QString(m_fsSpec).remove(QStringLiteral("PARTLABEL=")));
m_entryType = FstabEntry::Type::label;
m_deviceNode = findBlkIdDevice("PARTLABEL", QString(m_fsSpec).remove(QStringLiteral("PARTLABEL=")));
} else if (m_fsSpec.startsWith(QStringLiteral("/"))) {
m_entryType = FstabEntryType::deviceNode;
m_entryType = FstabEntry::Type::deviceNode;
m_deviceNode = m_fsSpec;
}
}
@ -154,7 +231,7 @@ static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QS
static void writeEntry(QFile& output, const FstabEntry& entry)
{
QTextStream s(&output);
if (entry.entryType() == FstabEntryType::comment) {
if (entry.entryType() == FstabEntry::Type::comment) {
s << entry.comment() << "\n";
return;
}
@ -177,34 +254,34 @@ static void writeEntry(QFile& output, const FstabEntry& entry)
<< entry.comment() << "\n";
}
bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename)
bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename)
{
bool rval = true;
const QString newFilename = QStringLiteral("%1.new").arg(filename);
QFile out(newFilename);
QTemporaryFile out;
out.setAutoRemove(false);
if (!out.open(QFile::ReadWrite | QFile::Truncate)) {
qWarning() << "could not open output file " << newFilename;
rval = false;
if (!out.open()) {
qWarning() << "could not open output file " << out.fileName();
return false;
} else {
for (const auto &e : fstabEntries)
writeEntry(out, e);
out.close();
const QString bakFilename = QStringLiteral("%1.bak").arg(filename);
QFile::remove(bakFilename);
ExternalCommand mvCmd(QStringLiteral("mv"), { filename, bakFilename } );
if (QFile::exists(filename) && !QFile::rename(filename, bakFilename)) {
qWarning() << "could not rename " << filename << " to " << bakFilename;
rval = false;
if ( !(mvCmd.run(-1) && mvCmd.exitCode() == 0) ) {
qWarning() << "could not backup " << filename << " to " << bakFilename;
return false;
}
if (rval && !QFile::rename(newFilename, filename)) {
qWarning() << "could not rename " << newFilename << " to " << filename;
rval = false;
ExternalCommand mvCmd2(QStringLiteral("mv"), { out.fileName(), filename } );
if ( !(mvCmd2.run(-1) && mvCmd2.exitCode() == 0) ) {
qWarning() << "could not move " << out.fileName() << " to " << filename;
return false;
}
}
return rval;
return true;
}

View File

@ -1,5 +1,5 @@
/*************************************************************************
* Copyright (C) 2017 by Andrius Štikonas <andrius@stikonas.eu> *
* Copyright (C) 2017-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -20,10 +20,12 @@
#include "util/libpartitionmanagerexport.h"
#include <memory>
#include <QList>
#include <QString>
enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment };
struct FstabEntryPrivate;
/** Base class for fstab handling.
@ -35,65 +37,88 @@ enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment };
class LIBKPMCORE_EXPORT FstabEntry
{
public:
enum class Type { deviceNode, uuid, label, partlabel, partuuid, comment };
FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq = 0, int passNumber = 0, const QString& comment = QString());
const QString& fsSpec() const {
return m_fsSpec; /**< @return the fs_spec field of fstab entry */
}
const QString& deviceNode() const {
return m_deviceNode; /**< @return the device node corresponding to fs_spec entry */
}
const QString& mountPoint() const {
return m_mountPoint; /**< @return the mount point (target) for the file system */
}
const QString& type() const {
return m_type; /**< @return the type of the file system */
}
const QStringList& options() const {
return m_options; /**< @return the mount options associated with the file system */
}
int dumpFreq() const {
return m_dumpFreq; /**< @return the fs_freq field of fstab entry */
}
int passNumber() const {
return m_passNumber; /**< @return the fs_passno field of fstab entry */
}
const QString& comment() const {
return m_comment; /**< @return commented part of the line in fstab file */
}
FstabEntryType entryType() const {
return m_entryType; /**< @return the type of fstab entry, e.g. device node or UUID or comment only */
}
/**
* @return the fs_spec field of fstab entry
*/
const QString& fsSpec() const;
/**
* @return the device node corresponding to fs_spec entry
*/
const QString& deviceNode() const;
/**
* @return the mount point (target) for the file system
*/
const QString& mountPoint() const;
/**
* @return the type of the file system
*/
const QString& type() const;
/**
* @return the mount options associated with the file system
*/
const QStringList& options() const;
/**
* @return the fs_freq field of fstab entry
*/
int dumpFreq() const;
/**
* @return the fs_passno field of fstab entry
*/
int passNumber() const;
/**
* @return commented part of the line in fstab file
*/
const QString& comment() const;
/**
* @return the type of fstab entry, e.g. device node or UUID or comment only
*/
Type entryType() const;
/**
* @param s the new value for the fs_spec field of fstab entry
*/
void setFsSpec(const QString& s);
void setMountPoint(const QString& s) {
m_mountPoint = s; /**< @param s the new value for the mount point */
}
void setOptions(const QStringList& s) {
m_options = s; /**< @param s the new list with the mount options */
}
void setDumpFreq(int s) {
m_dumpFreq = s; /**< @param s the new value for the dump frequency */
}
void setPassNumber(int s) {
m_passNumber = s; /**< @param s the new value for the pass number */
}
/**
* @param s the new value for the mount point
*/
void setMountPoint(const QString& s);
/**
* @param s the new list with the mount options
*/
void setOptions(const QStringList& s);
/**
* @param s the new value for the dump frequency
*/
void setDumpFreq(int s);
/**
* @param s the new value for the pass number
*/
void setPassNumber(int s);
private:
QString m_fsSpec;
QString m_deviceNode;
QString m_mountPoint;
QString m_type;
QStringList m_options;
int m_dumpFreq;
int m_passNumber;
QString m_comment;
FstabEntryType m_entryType;
std::shared_ptr<FstabEntryPrivate> d;
};
typedef QList<FstabEntry> FstabEntryList;
LIBKPMCORE_EXPORT FstabEntryList readFstabEntries(const QString& fstabPath = QStringLiteral("/etc/fstab"));
LIBKPMCORE_EXPORT QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath = QStringLiteral("/etc/fstab"));
LIBKPMCORE_EXPORT bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename = QStringLiteral("/etc/fstab"));
LIBKPMCORE_EXPORT bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename = QStringLiteral("/etc/fstab"));
#endif

View File

@ -18,14 +18,16 @@
#include "core/lvmdevice.h"
#include "core/partition.h"
#include "core/partitiontable.h"
#include "core/volumemanagerdevice_p.h"
#include "fs/filesystem.h"
#include "fs/lvm2_pv.h"
#include "fs/luks.h"
#include "fs/filesystemfactory.h"
#include "core/partitiontable.h"
#include "util/externalcommand.h"
#include "util/helpers.h"
#include "util/globallog.h"
#include "util/report.h"
#include <QRegularExpression>
@ -34,26 +36,43 @@
#include <KLocalizedString>
#define d_ptr std::static_pointer_cast<LvmDevicePrivate>(d)
class LvmDevicePrivate : public VolumeManagerDevicePrivate
{
public:
qint64 m_peSize;
qint64 m_totalPE;
qint64 m_allocPE;
qint64 m_freePE;
QString m_UUID;
mutable QStringList m_LVPathList;
QVector <const Partition*> m_PVs;
mutable std::unique_ptr<QHash<QString, qint64>> m_LVSizeMap;
};
/** Constructs a representation of LVM device with initialized LV as Partitions
*
* @param vgName Volume Group name
* @param iconName Icon representing LVM Volume group
*/
LvmDevice::LvmDevice(const QString& vgName, const QString& iconName)
: VolumeManagerDevice(vgName,
: VolumeManagerDevice(std::make_shared<LvmDevicePrivate>(),
vgName,
(QStringLiteral("/dev/") + vgName),
getPeSize(vgName),
getTotalPE(vgName),
iconName,
Device::LVM_Device)
Device::Type::LVM_Device)
{
m_peSize = logicalSize();
m_totalPE = totalLogical();
m_freePE = getFreePE(vgName);
m_allocPE = m_totalPE - m_freePE;
m_UUID = getUUID(vgName);
m_LVPathList = new QStringList(getLVs(vgName));
m_LVSizeMap = new QHash<QString, qint64>();
d_ptr->m_peSize = logicalSize();
d_ptr->m_totalPE = totalLogical();
d_ptr->m_freePE = getFreePE(vgName);
d_ptr->m_allocPE = d_ptr->m_totalPE - d_ptr->m_freePE;
d_ptr->m_UUID = getUUID(vgName);
d_ptr->m_LVPathList = getLVs(vgName);
d_ptr->m_LVSizeMap = std::make_unique<QHash<QString, qint64>>();
initPartitions();
}
@ -64,36 +83,47 @@ LvmDevice::LvmDevice(const QString& vgName, const QString& iconName)
*/
QVector<const Partition*> LvmDevice::s_DirtyPVs;
/**
* shared list of PVs paths that are member of VGs that will be deleted soon.
*/
QVector<const Partition*> LvmDevice::s_OrphanPVs;
LvmDevice::~LvmDevice()
{
delete m_LVPathList;
delete m_LVSizeMap;
}
void LvmDevice::initPartitions()
{
qint64 firstUsable = 0;
qint64 lastusable = totalPE() - 1;
PartitionTable* pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastusable);
qint64 lastUsable = totalPE() - 1;
PartitionTable* pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastUsable);
for (const auto &p : scanPartitions(pTable)) {
LVSizeMap()->insert(p->partitionPath(), p->length());
pTable->append(p);
}
pTable->updateUnallocated(*this);
if (pTable)
pTable->updateUnallocated(*this);
else
pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastUsable);
setPartitionTable(pTable);
}
/**
* Scan LVM LV Partitions
*
* @param pTable Virtual PartitionTable of LVM device
* @return an initialized Partition(LV) list
*/
const QList<Partition*> LvmDevice::scanPartitions(PartitionTable* pTable) const
{
QList<Partition*> pList;
for (const auto &lvPath : partitionNodes()) {
pList.append(scanPartition(lvPath, pTable));
Partition *p = scanPartition(lvPath, pTable);
pList.append(p);
}
return pList;
}
@ -129,7 +159,7 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl
bool mounted;
// Handle LUKS partition
if (fs->type() == FileSystem::Luks) {
if (fs->type() == FileSystem::Type::Luks) {
r |= PartitionRole::Luks;
FS::luks* luksFs = static_cast<FS::luks*>(fs);
luksFs->initLUKS();
@ -141,9 +171,9 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl
mountPoint = FileSystem::detectMountPoint(fs, lvPath);
mounted = FileSystem::detectMountStatus(fs, lvPath);
if (mountPoint != QString() && fs->type() != FileSystem::LinuxSwap) {
if (mountPoint != QString() && fs->type() != FileSystem::Type::LinuxSwap) {
const QStorageInfo storage = QStorageInfo(mountPoint);
if (logicalSize() > 0 && fs->type() != FileSystem::Luks && mounted && storage.isValid())
if (logicalSize() > 0 && fs->type() != FileSystem::Type::Luks && mounted && storage.isValid())
fs->setSectorsUsed( (storage.bytesTotal() - storage.bytesFree()) / logicalSize() );
}
else if (fs->supportGetUsed() == FileSystem::cmdSupportFileSystem)
@ -175,23 +205,26 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl
*/
void LvmDevice::scanSystemLVM(QList<Device*>& devices)
{
LvmDevice::s_OrphanPVs.clear();
QList<LvmDevice*> lvmList;
for (const auto &vgName : getVGs()) {
lvmList.append(new LvmDevice(vgName));
}
// Some LVM operations require additional information about LVM physical volumes which we store in LVM::pvList
LVM::pvList = FS::lvm2_pv::getPVs(devices);
// Some LVM operations require additional information about LVM physical volumes which we store in LVM::pvList::list()
LVM::pvList::list().clear();
LVM::pvList::list().append(FS::lvm2_pv::getPVs(devices));
// Look for LVM physical volumes in LVM VGs
for (const auto &d : lvmList) {
devices.append(d);
LVM::pvList.append(FS::lvm2_pv::getPVinNode(d->partitionTable()));
LVM::pvList::list().append(FS::lvm2_pv::getPVinNode(d->partitionTable()));
}
// Inform LvmDevice about which physical volumes form that particular LvmDevice
for (const auto &d : lvmList)
for (const auto &p : qAsConst(LVM::pvList))
for (const auto &p : qAsConst(LVM::pvList::list()))
if (p.vgName() == d->name())
d->physicalVolumes().append(p.partition());
@ -225,9 +258,9 @@ const QStringList LvmDevice::deviceNodes() const
return pvList;
}
const QStringList LvmDevice::partitionNodes() const
const QStringList& LvmDevice::partitionNodes() const
{
return *LVPathList();
return d_ptr->m_LVPathList;
}
qint64 LvmDevice::partitionSize(QString& partitionPath) const
@ -240,7 +273,7 @@ const QStringList LvmDevice::getVGs()
QStringList vgList;
QString output = getField(QStringLiteral("vg_name"));
if (!output.isEmpty()) {
const QStringList vgNameList = output.split(QStringLiteral("\n"), QString::SkipEmptyParts);
const QStringList vgNameList = output.split(QLatin1Char('\n'), QString::SkipEmptyParts);
for (const auto &vgName : vgNameList) {
vgList.append(vgName.trimmed());
}
@ -254,7 +287,7 @@ const QStringList LvmDevice::getLVs(const QString& vgName)
QString cmdOutput = getField(QStringLiteral("lv_path"), vgName);
if (cmdOutput.size()) {
const QStringList tempPathList = cmdOutput.split(QStringLiteral("\n"), QString::SkipEmptyParts);
const QStringList tempPathList = cmdOutput.split(QLatin1Char('\n'), QString::SkipEmptyParts);
for (const auto &lvPath : tempPathList) {
lvPathList.append(lvPath.trimmed());
}
@ -333,6 +366,7 @@ qint64 LvmDevice::getTotalLE(const QString& lvPath)
return match.captured(1).toInt();
}
}
Log(Log::Level::error) << xi18nc("@info:status", "An error occurred while running lvdisplay.");
return -1;
}
@ -419,8 +453,7 @@ bool LvmDevice::movePV(Report& report, const QString& pvPath, const QStringList&
if (FS::lvm2_pv::getAllocatedPE(pvPath) <= 0)
return true;
QStringList args = QStringList();
args << QStringLiteral("pvmove");
QStringList args = { QStringLiteral("pvmove") };
args << pvPath;
if (!destinations.isEmpty())
for (const auto &destPath : destinations)
@ -432,8 +465,7 @@ bool LvmDevice::movePV(Report& report, const QString& pvPath, const QStringList&
bool LvmDevice::createVG(Report& report, const QString vgName, const QVector<const Partition*>& pvList, const qint32 peSize)
{
QStringList args = QStringList();
args << QStringLiteral("vgcreate") << QStringLiteral("--physicalextentsize") << QString::number(peSize);
QStringList args = { QStringLiteral("vgcreate"), QStringLiteral("--physicalextentsize"), QString::number(peSize) };
args << vgName;
for (const auto &p : pvList) {
if (p->roles().has(PartitionRole::Luks))
@ -492,3 +524,43 @@ bool LvmDevice::activateLV(const QString& lvPath)
lvPath });
return deactivate.run(-1) && deactivate.exitCode() == 0;
}
qint64 LvmDevice::peSize() const
{
return d_ptr->m_peSize;
}
qint64 LvmDevice::totalPE() const
{
return d_ptr->m_totalPE;
}
qint64 LvmDevice::allocatedPE() const
{
return d_ptr->m_allocPE;
}
qint64 LvmDevice::freePE() const
{
return d_ptr->m_freePE;
}
QString LvmDevice::UUID() const
{
return d_ptr->m_UUID;
}
QVector <const Partition*>& LvmDevice::physicalVolumes()
{
return d_ptr->m_PVs;
}
const QVector <const Partition*>& LvmDevice::physicalVolumes() const
{
return d_ptr->m_PVs;
}
std::unique_ptr<QHash<QString, qint64>>& LvmDevice::LVSizeMap() const
{
return d_ptr->m_LVSizeMap;
}

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_LVMDEVICE_H)
#ifndef KPMCORE_LVMDEVICE_H
#define KPMCORE_LVMDEVICE_H
#include "core/device.h"
@ -52,12 +51,12 @@ public:
public:
const QStringList deviceNodes() const override;
const QStringList partitionNodes() const override;
const QStringList& partitionNodes() const override;
qint64 partitionSize(QString& partitionPath) const override;
static QVector<const Partition*> s_DirtyPVs;
static QVector<const Partition*> s_OrphanPVs;
public:
static void scanSystemLVM(QList<Device*>& devices);
static const QStringList getVGs();
@ -89,54 +88,22 @@ public:
static bool activateVG(Report& report, const LvmDevice& d);
protected:
void initPartitions() override;
const QList<Partition*> scanPartitions(PartitionTable* pTable) const;
Partition* scanPartition(const QString& lvPath, PartitionTable* pTable) const;
qint64 mappedSector(const QString& lvPath, qint64 sector) const override;
public:
qint64 peSize() const {
return m_peSize;
}
qint64 totalPE() const {
return m_totalPE;
}
qint64 allocatedPE() const {
return m_allocPE;
}
qint64 freePE() const {
return m_freePE;
}
QString UUID() const {
return m_UUID;
}
QStringList* LVPathList() const {
return m_LVPathList;
}
QVector <const Partition*>& physicalVolumes() {
return m_PVs;
}
const QVector <const Partition*>& physicalVolumes() const {
return m_PVs;
}
qint64 peSize() const;
qint64 totalPE() const;
qint64 allocatedPE() const;
qint64 freePE() const;
QString UUID() const;
QVector <const Partition*>& physicalVolumes();
const QVector <const Partition*>& physicalVolumes() const;
protected:
QHash<QString, qint64>* LVSizeMap() const {
return m_LVSizeMap;
}
private:
qint64 m_peSize;
qint64 m_totalPE;
qint64 m_allocPE;
qint64 m_freePE;
QString m_UUID;
mutable QStringList* m_LVPathList;
QVector <const Partition*> m_PVs;
mutable QHash<QString, qint64>* m_LVSizeMap;
std::unique_ptr<QHash<QString, qint64>>& LVSizeMap() const;
};
#endif

View File

@ -25,9 +25,6 @@
#include <QDBusReply>
#include <QMutex>
#include <pwd.h>
#include <unistd.h>
/** Constructs an OperationRunner.
@param ostack the OperationStack to act on
*/
@ -50,15 +47,6 @@ void OperationRunner::run()
bool status = true;
// Disable Plasma removable device automounting
unsigned int currentUid = getuid(); // 0 if running as root
char *login = getlogin();
if (login != nullptr){
passwd* pwnam = getpwnam(login);
if (pwnam != nullptr) {
unsigned int userId = pwnam->pw_uid; // uid of original user before sudo
seteuid(userId);
}
}
QStringList modules;
QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("sessionBus"));
QDBusInterface kdedInterface( QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QStringLiteral("org.kde.kded5"), bus );
@ -69,7 +57,6 @@ void OperationRunner::run()
bool automounter = modules.contains(automounterService);
if (automounter)
kdedInterface.call( QStringLiteral("unloadModule"), automounterService );
seteuid(currentUid);
for (int i = 0; i < numOperations(); i++) {
suspendMutex().lock();

View File

@ -555,7 +555,7 @@ void OperationStack::addDevice(Device* d)
static bool deviceLessThan(const Device* d1, const Device* d2)
{
// Display alphabetically sorted disk devices above LVM VGs
if (d1->type() == Device::LVM_Device && d2->type() == Device::Disk_Device )
if (d1->type() == Device::Type::LVM_Device && d2->type() == Device::Type::Disk_Device )
return false;
return d1->deviceNode() <= d2->deviceNode();

View File

@ -80,10 +80,10 @@ public:
New, /**< from a NewOperation */
Copy, /**< from a CopyOperation */
Restore, /**< from a RestoreOperation */
StateNone = None,
StateNew = New,
StateCopy = Copy,
StateRestore = Restore
StateNone __attribute__((deprecated("Use Partition::State::None"))) = None,
StateNew __attribute__((deprecated("Use Partition::State::New"))) = New,
StateCopy __attribute__((deprecated("Use Partition::State::Copy"))) = Copy,
StateRestore __attribute__((deprecated("Use Partition::State::Restore"))) = Restore
};
Partition(PartitionNode* parent, const Device& device, const PartitionRole& role, FileSystem* fs, qint64 sectorStart, qint64 sectorEnd, QString partitionPath, PartitionTable::Flags availableFlags = PartitionTable::FlagNone, const QString& mountPoint = QString(), bool mounted = false, PartitionTable::Flags activeFlags = PartitionTable::FlagNone, State state = State::None);

View File

@ -85,10 +85,10 @@ bool PartitionAlignment::isAligned(const Device& d, const Partition& p, bool qui
bool PartitionAlignment::isAligned(const Device& d, const Partition& p, qint64 newFirst, qint64 newLast, bool quiet)
{
if (firstDelta(d, p, newFirst) && !quiet)
Log(Log::warning) << xi18nc("@info:status", "Partition <filename>%1</filename> is not properly aligned (first sector: %2, modulo: %3).", p.deviceNode(), newFirst, firstDelta(d, p, newFirst));
Log(Log::Level::warning) << xi18nc("@info:status", "Partition <filename>%1</filename> is not properly aligned (first sector: %2, modulo: %3).", p.deviceNode(), newFirst, firstDelta(d, p, newFirst));
if (lastDelta(d, p, newLast) && !quiet)
Log(Log::warning) << xi18nc("@info:status", "Partition <filename>%1</filename> is not properly aligned (last sector: %2, modulo: %3).", p.deviceNode(), newLast, lastDelta(d, p, newLast));
Log(Log::Level::warning) << xi18nc("@info:status", "Partition <filename>%1</filename> is not properly aligned (last sector: %2, modulo: %3).", p.deviceNode(), newLast, lastDelta(d, p, newLast));
return firstDelta(d, p, newFirst) == 0 && lastDelta(d, p, newLast) == 0;
}

View File

@ -274,7 +274,7 @@ QStringList PartitionTable::flagNames(Flags flags)
bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent, qint64& start, qint64& end)
{
if (d.type() == Device::Disk_Device) {
if (d.type() == Device::Type::Disk_Device) {
const DiskDevice& device = dynamic_cast<const DiskDevice&>(d);
if (!parent.isRoot()) {
Partition* extended = dynamic_cast<Partition*>(&parent);
@ -295,7 +295,7 @@ bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent,
}
return end - start + 1 >= PartitionAlignment::sectorAlignment(device);
} else if (d.type() == Device::LVM_Device) {
} else if (d.type() == Device::Type::LVM_Device || d.type() == Device::Type::SoftwareRAID_Device) {
if (end - start + 1 > 0) {
return true;
}
@ -319,13 +319,13 @@ Partition* createUnallocated(const Device& device, PartitionNode& parent, qint64
r |= PartitionRole::Logical;
// Mark unallocated space in LVM VG as LVM LV so that pasting can be easily disabled (it does not work yet)
if (device.type() == Device::LVM_Device)
if (device.type() == Device::Type::LVM_Device)
r |= PartitionRole::Lvm_Lv;
if (!PartitionTable::getUnallocatedRange(device, parent, start, end))
return nullptr;
return new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Unknown, start, end, device.logicalSize()), start, end, QString());
return new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Type::Unknown, start, end, device.logicalSize()), start, end, QString());
}
/** Removes all unallocated children from a PartitionNode
@ -379,7 +379,7 @@ void PartitionTable::insertUnallocated(const Device& d, PartitionNode* p, qint64
qint64 lastEnd = start;
if (d.type() == Device::LVM_Device && !p->children().isEmpty()) {
if (d.type() == Device::Type::LVM_Device && !p->children().isEmpty()) {
// rearranging the sectors of all partitions to keep unallocated space at the end
lastEnd = 0;
std::sort(children().begin(), children().end(), [](const Partition* p1, const Partition* p2) { return p1->deviceNode() < p2->deviceNode(); });
@ -402,18 +402,26 @@ void PartitionTable::insertUnallocated(const Device& d, PartitionNode* p, qint64
}
}
// Take care of the free space between the end of the last child and the end
// of the device or the extended partition.
qint64 parentEnd = lastUsable();
if (!p->isRoot()) {
Partition* extended = dynamic_cast<Partition*>(p);
parentEnd = extended ? extended->lastSector() : -1;
Q_ASSERT(extended);
if (d.type() == Device::Type::LVM_Device)
{
const LvmDevice& lvm = static_cast<const LvmDevice&>(d);
p->insert(createUnallocated(d, *p, lastEnd, lastEnd + lvm.freePE() - 1));
}
else
{
// Take care of the free space between the end of the last child and the end
// of the device or the extended partition.
qint64 parentEnd = lastUsable();
if (parentEnd >= firstUsable() && parentEnd >= lastEnd)
p->insert(createUnallocated(d, *p, lastEnd, parentEnd));
if (!p->isRoot()) {
Partition* extended = dynamic_cast<Partition*>(p);
parentEnd = extended ? extended->lastSector() : -1;
Q_ASSERT(extended);
}
if (parentEnd >= firstUsable() && parentEnd >= lastEnd)
p->insert(createUnallocated(d, *p, lastEnd, parentEnd));
}
}
/** Updates the unallocated Partitions for this PartitionTable.
@ -428,7 +436,7 @@ void PartitionTable::updateUnallocated(const Device& d)
qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t)
{
Q_UNUSED(t)
if (d.type() == Device::LVM_Device) {
if (d.type() == Device::Type::LVM_Device || d.type() == Device::Type::SoftwareRAID_Device) {
return 0;
}
@ -518,7 +526,7 @@ bool PartitionTable::tableTypeIsReadOnly(TableType l)
*/
bool PartitionTable::isSectorBased(const Device& d) const
{
if (d.type() == Device::Disk_Device) {
if (d.type() == Device::Type::Disk_Device) {
const DiskDevice& diskDevice = dynamic_cast<const DiskDevice&>(d);
if (type() == PartitionTable::msdos) {

View File

@ -0,0 +1,7 @@
set(RAID_SRC
core/raid/softwareraid.cpp
)
set(RAID_LIB_HDRS
core/raid/softwareraid.h
)

View File

@ -0,0 +1,480 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "softwareraid.h"
#include "backend/corebackend.h"
#include "backend/corebackendmanager.h"
#include "core/partition.h"
#include "core/volumemanagerdevice_p.h"
#include "fs/filesystem.h"
#include "fs/filesystemfactory.h"
#include "util/externalcommand.h"
#include <KLocalizedString>
#include <QFile>
#include <QRegularExpression>
#define d_ptr std::static_pointer_cast<SoftwareRAIDPrivate>(d)
class SoftwareRAIDPrivate : public VolumeManagerDevicePrivate
{
public:
qint32 m_raidLevel;
qint64 m_chunkSize;
qint64 m_totalChunk;
qint64 m_arraySize;
QString m_UUID;
QStringList m_devicePathList;
SoftwareRAID::Status m_status;
};
SoftwareRAID::SoftwareRAID(const QString& name, SoftwareRAID::Status status, const QString& iconName)
: VolumeManagerDevice(std::make_shared<SoftwareRAIDPrivate>(),
name,
(QStringLiteral("/dev/") + name),
getChunkSize(QStringLiteral("/dev/") + name),
getTotalChunk(QStringLiteral("/dev/") + name),
iconName,
Device::Type::SoftwareRAID_Device)
{
d_ptr->m_raidLevel = getRaidLevel(deviceNode());
d_ptr->m_chunkSize = logicalSize();
d_ptr->m_totalChunk = totalLogical();
d_ptr->m_arraySize = getArraySize(deviceNode());
d_ptr->m_UUID = getUUID(deviceNode());
d_ptr->m_devicePathList = getDevicePathList(deviceNode());
d_ptr->m_status = status;
initPartitions();
}
const QStringList SoftwareRAID::deviceNodes() const
{
return d_ptr->m_devicePathList;
}
const QStringList& SoftwareRAID::partitionNodes() const
{
return {};
}
qint64 SoftwareRAID::partitionSize(QString &partitionPath) const
{
Q_UNUSED(partitionPath)
return 0;
}
bool SoftwareRAID::growArray(Report &report, const QStringList &devices)
{
Q_UNUSED(report)
Q_UNUSED(devices)
return false;
}
bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices)
{
Q_UNUSED(report)
Q_UNUSED(devices)
return false;
}
QString SoftwareRAID::prettyName() const
{
QString raidInfo;
if (status() == SoftwareRAID::Status::Active)
raidInfo = xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel());
else if (status() == SoftwareRAID::Status::Recovery)
raidInfo = xi18nc("@item:inlistbox [RAID level - Recovering]", " [RAID %1 - Recovering]", raidLevel());
else if (status() == SoftwareRAID::Status::Resync)
raidInfo = xi18nc("@item:inlistbox [RAID level - Resyncing]", " [RAID %1 - Resyncing]", raidLevel());
else
raidInfo = QStringLiteral(" [RAID]");
return VolumeManagerDevice::prettyName() + raidInfo;
}
bool SoftwareRAID::operator ==(const Device& other) const
{
bool equalDeviceNode = Device::operator ==(other);
if (other.type() == Device::Type::SoftwareRAID_Device) {
const SoftwareRAID& raid = static_cast<const SoftwareRAID&>(other);
if (!equalDeviceNode)
return raid.uuid() == uuid();
}
return equalDeviceNode;
}
qint32 SoftwareRAID::raidLevel() const
{
return d_ptr->m_raidLevel;
}
qint64 SoftwareRAID::chunkSize() const
{
return d_ptr->m_chunkSize;
}
qint64 SoftwareRAID::totalChunk() const
{
return d_ptr->m_totalChunk;
}
qint64 SoftwareRAID::arraySize() const
{
return d_ptr->m_arraySize;
}
QString SoftwareRAID::uuid() const
{
return d_ptr->m_UUID;
}
QStringList SoftwareRAID::devicePathList() const
{
return d_ptr->m_devicePathList;
}
SoftwareRAID::Status SoftwareRAID::status() const
{
return d_ptr->m_status;
}
void SoftwareRAID::setStatus(SoftwareRAID::Status status)
{
d_ptr->m_status = status;
}
void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
{
QStringList availableInConf;
// TODO: Support custom config files.
QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf"));
if (!config.isEmpty()) {
QRegularExpression re(QStringLiteral("([\\t\\r\\n\\f\\s]|INACTIVE-)ARRAY \\/dev\\/([\\/\\w-]+)"));
QRegularExpressionMatchIterator i = re.globalMatch(config);
while (i.hasNext()) {
QRegularExpressionMatch reMatch = i.next();
QString deviceName = reMatch.captured(2).trimmed();
availableInConf << deviceName;
}
}
QFile mdstat(QStringLiteral("/proc/mdstat"));
if (mdstat.open(QIODevice::ReadOnly)) {
QTextStream stream(&mdstat);
QString content = stream.readAll();
mdstat.close();
QRegularExpression re(QStringLiteral("md([\\/\\w]+)\\s+:\\s+([\\w]+)"));
QRegularExpressionMatchIterator i = re.globalMatch(content);
while (i.hasNext()) {
QRegularExpressionMatch reMatch = i.next();
QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed();
QString status = reMatch.captured(2).trimmed();
SoftwareRAID* d = static_cast<SoftwareRAID *>(CoreBackendManager::self()->backend()->scanDevice(deviceNode));
// Just to prevent segfault in some case
if (d == nullptr)
continue;
const QStringList constAvailableInConf = availableInConf;
for (const QString& path : constAvailableInConf)
if (getUUID(QStringLiteral("/dev/") + path) == d->uuid())
availableInConf.removeAll(path);
devices << d;
if (status == QStringLiteral("inactive"))
d->setStatus(SoftwareRAID::Status::Inactive);
if (d->raidLevel() > 0) {
QRegularExpression reMirrorStatus(d->name() + QStringLiteral("\\s+:\\s+(.*\\n\\s+)+\\[[=>.]+\\]\\s+(resync|recovery)"));
QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(content);
if (reMirrorStatusMatch.hasMatch()) {
if (reMirrorStatusMatch.captured(2) == QStringLiteral("resync"))
d->setStatus(SoftwareRAID::Status::Resync);
else if (reMirrorStatusMatch.captured(2) == QStringLiteral("recovery"))
d->setStatus(SoftwareRAID::Status::Recovery);
}
}
}
}
for (const QString& name : qAsConst(availableInConf)) {
SoftwareRAID *raidDevice = new SoftwareRAID(name, SoftwareRAID::Status::Inactive);
devices << raidDevice;
}
}
qint32 SoftwareRAID::getRaidLevel(const QString &path)
{
QString output = getDetail(path);
if (!output.isEmpty()) {
QRegularExpression re(QStringLiteral("Raid Level :\\s+\\w+(\\d+)"));
QRegularExpressionMatch reMatch = re.match(output);
if (reMatch.hasMatch())
return reMatch.captured(1).toLongLong();
}
return -1;
}
qint64 SoftwareRAID::getChunkSize(const QString &path)
{
if (getRaidLevel(path) == 1) {
QStringList devices = getDevicePathList(path);
if (!devices.isEmpty()) {
QString device = devices[0];
// Look sector size for the first device/partition on the list, as RAID 1 is composed by mirrored devices
ExternalCommand sectorSize(QStringLiteral("blockdev"), { QStringLiteral("--getss"), device });
if (sectorSize.run(-1) && sectorSize.exitCode() == 0) {
int sectors = sectorSize.output().trimmed().toLongLong();
return sectors;
}
}
}
else {
QString output = getDetail(path);
if (!output.isEmpty()) {
QRegularExpression re(QStringLiteral("Chunk Size :\\s+(\\d+)"));
QRegularExpressionMatch reMatch = re.match(output);
if (reMatch.hasMatch())
return reMatch.captured(1).toLongLong();
}
}
return -1;
}
qint64 SoftwareRAID::getTotalChunk(const QString &path)
{
return getArraySize(path) / getChunkSize(path);
}
qint64 SoftwareRAID::getArraySize(const QString &path)
{
QString output = getDetail(path);
if (!output.isEmpty()) {
QRegularExpression re(QStringLiteral("Array Size :\\s+(\\d+)"));
QRegularExpressionMatch reMatch = re.match(output);
if (reMatch.hasMatch())
return reMatch.captured(1).toLongLong() * 1024;
}
return -1;
}
QString SoftwareRAID::getUUID(const QString &path)
{
QString output = getDetail(path);
if (!output.isEmpty()) {
QRegularExpression re(QStringLiteral("UUID :\\s+([\\w:]+)"));
QRegularExpressionMatch reMatch = re.match(output);
if (reMatch.hasMatch())
return reMatch.captured(1);
}
// If UUID was not found in detail output, it should be searched in config file
// TODO: Support custom config files.
QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf"));
if (!config.isEmpty()) {
QRegularExpression re(QStringLiteral("([\\t\\r\\n\\f\\s]|INACTIVE-)ARRAY \\/dev\\/md([\\/\\w-]+)(.*)"));
QRegularExpressionMatchIterator i = re.globalMatch(config);
while (i.hasNext()) {
QRegularExpressionMatch reMatch = i.next();
QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(2).trimmed();
QString otherInfo = reMatch.captured(3).trimmed();
// Consider device node as name=host:deviceNode when the captured device node string has '-' character
// It happens when user have included the device to config file using 'mdadm --examine --scan'
if (deviceNode.contains(QLatin1Char('-'))) {
QRegularExpression reName(QStringLiteral("name=[\\w:]+\\/dev\\/md\\/([\\/\\w]+)"));
QRegularExpressionMatch nameMatch = reName.match(otherInfo);
if (nameMatch.hasMatch())
deviceNode = nameMatch.captured(1);
}
if (deviceNode == path) {
QRegularExpression reUUID(QStringLiteral("(UUID=|uuid=)([\\w:]+)"));
QRegularExpressionMatch uuidMatch = reUUID.match(otherInfo);
if (uuidMatch.hasMatch())
return uuidMatch.captured(2);
}
}
}
return QString();
}
QStringList SoftwareRAID::getDevicePathList(const QString &path)
{
QStringList result;
QString detail = getDetail(path);
if (!detail.isEmpty()) {
QRegularExpression re(QStringLiteral("\\s+\\/dev\\/(\\w+)"));
QRegularExpressionMatchIterator i = re.globalMatch(detail);
while (i.hasNext()) {
QRegularExpressionMatch match = i.next();
QString device = QStringLiteral("/dev/") + match.captured(1);
if (device != path)
result << device;
}
}
return result;
}
bool SoftwareRAID::isRaidPath(const QString &path)
{
return !getDetail(path).isEmpty();
}
bool SoftwareRAID::createSoftwareRAID(Report &report,
const QString &name,
const QStringList devicePathList,
const qint32 raidLevel,
const qint32 chunkSize)
{
return false;
}
bool SoftwareRAID::deleteSoftwareRAID(Report &report,
SoftwareRAID &raidDevice)
{
Q_UNUSED(report)
Q_UNUSED(raidDevice)
return false;
}
bool SoftwareRAID::assembleSoftwareRAID(const QString& deviceNode)
{
if (!isRaidPath(deviceNode))
return false;
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--assemble"), QStringLiteral("--scan"), deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::stopSoftwareRAID(const QString& deviceNode)
{
if (!isRaidPath(deviceNode))
return false;
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--manage"), QStringLiteral("--stop"), deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool SoftwareRAID::reassembleSoftwareRAID(const QString &deviceNode)
{
return stopSoftwareRAID(deviceNode) && assembleSoftwareRAID(deviceNode);
}
bool SoftwareRAID::isRaidMember(const QString &path)
{
QFile mdstat(QStringLiteral("/proc/mdstat"));
if (!mdstat.open(QIODevice::ReadOnly))
return false;
QTextStream stream(&mdstat);
QString content = stream.readAll();
mdstat.close();
QRegularExpression re(QStringLiteral("(\\w+)\\[\\d+\\]"));
QRegularExpressionMatchIterator i = re.globalMatch(content);
while (i.hasNext()) {
QRegularExpressionMatch reMatch = i.next();
QString match = QStringLiteral("/dev/") + reMatch.captured(1);
if (match == path)
return true;
}
return false;
}
void SoftwareRAID::initPartitions()
{
}
qint64 SoftwareRAID::mappedSector(const QString &partitionPath, qint64 sector) const
{
return -1;
}
QString SoftwareRAID::getDetail(const QString &path)
{
ExternalCommand cmd(QStringLiteral("mdadm"),
{ QStringLiteral("--misc"), QStringLiteral("--detail"), path });
return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString();
}
QString SoftwareRAID::getRAIDConfiguration(const QString &configurationPath)
{
QFile config(configurationPath);
if (!config.open(QIODevice::ReadOnly))
return QString();
QTextStream stream(&config);
QString result = stream.readAll();
config.close();
return result;
}

View File

@ -0,0 +1,103 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_SOFTWARERAID_H)
#define KPMCORE_SOFTWARERAID_H
#include "core/volumemanagerdevice.h"
#include "util/libpartitionmanagerexport.h"
#include "util/report.h"
class LIBKPMCORE_EXPORT SoftwareRAID : public VolumeManagerDevice
{
Q_DISABLE_COPY(SoftwareRAID)
public:
enum class Status {
Active,
Inactive,
Resync,
Recovery,
};
SoftwareRAID(const QString& name,
SoftwareRAID::Status status = SoftwareRAID::Status::Active,
const QString& iconName = QString());
const QStringList deviceNodes() const override;
const QStringList& partitionNodes() const override;
qint64 partitionSize(QString &partitionPath) const override;
virtual bool growArray(Report& report, const QStringList& devices);
virtual bool shrinkArray(Report& report, const QStringList& devices);
virtual QString prettyName() const override;
virtual bool operator==(const Device& other) const override;
qint32 raidLevel() const;
qint64 chunkSize() const;
qint64 totalChunk() const;
qint64 arraySize() const;
QString uuid() const;
QStringList devicePathList() const;
SoftwareRAID::Status status() const;
void setStatus(SoftwareRAID::Status status);
public:
static void scanSoftwareRAID(QList<Device*>& devices);
static qint32 getRaidLevel(const QString& path);
static qint64 getChunkSize(const QString& path);
static qint64 getTotalChunk(const QString& path);
static qint64 getArraySize(const QString& path);
static QString getUUID(const QString& path);
static QStringList getDevicePathList(const QString& path);
static bool isRaidPath(const QString& path);
static bool createSoftwareRAID(Report& report,
const QString& name,
const QStringList devicePathList,
const qint32 raidLevel,
const qint32 chunkSize);
static bool deleteSoftwareRAID(Report& report,
SoftwareRAID& raidDevice);
static bool assembleSoftwareRAID(const QString& deviceNode);
static bool stopSoftwareRAID(const QString& deviceNode);
static bool reassembleSoftwareRAID(const QString& deviceNode);
static bool isRaidMember(const QString& path);
protected:
void initPartitions() override;
qint64 mappedSector(const QString &partitionPath, qint64 sector) const override;
private:
static QString getDetail(const QString& path);
static QString getRAIDConfiguration(const QString& configurationPath);
};
#endif // SOFTWARERAID_H

View File

@ -18,78 +18,78 @@
#include "core/smartattribute.h"
#include "core/smartstatus.h"
#include "core/smartattributeparseddata.h"
#include <QLocale>
#include <KLocalizedString>
#include <KFormat>
#include <atasmart.h>
static QString getAttrName(qint32 id);
static QString getAttrDescription(qint32 id);
static QString getPrettyValue(quint64 value, qint64 unit);
static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a);
static QString getRaw(const uint8_t*);
static QString getPrettyValue(quint64 value, SmartAttributeUnit unit);
static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a);
static QString getRaw(quint64 raw);
SmartAttribute::SmartAttribute(const SkSmartAttributeParsedData* a) :
m_Id(a->id),
m_Name(getAttrName(a->id)),
m_Desc(getAttrDescription(a->id)),
m_FailureType(a->prefailure ? PreFailure : OldAge),
m_UpdateType(a->online ? Online : Offline),
m_Current(a->current_value_valid ? a->current_value : -1),
m_Worst(a->worst_value_valid ? a->worst_value : -1),
m_Threshold(a->threshold_valid ? a->threshold : -1),
m_Raw(getRaw(a->raw)),
SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) :
m_Id(a.id()),
m_Name(getAttrName(a.id())),
m_Desc(getAttrDescription(a.id())),
m_FailureType(a.prefailure() ? FailureType::PreFailure : FailureType::OldAge),
m_UpdateType(a.online() ? UpdateType::Online : UpdateType::Offline),
m_Current(a.currentValueValid() ? a.currentValue() : -1),
m_Worst(a.worstValueValid() ? a.worstValue() : -1),
m_Threshold(a.thresholdValid() ? a.threshold() : -1),
m_Raw(getRaw(a.raw())),
m_Assessment(getAssessment(a)),
m_Value(getPrettyValue(a->pretty_value, a->pretty_unit))
m_Value(getPrettyValue(a.prettyValue(), a.prettyUnit()))
{
}
QString SmartAttribute::assessmentToString(Assessment a)
{
switch (a) {
case Failing:
case Assessment::Failing:
return xi18nc("@item:intable", "failing");
case HasFailed:
case Assessment::HasFailed:
return xi18nc("@item:intable", "has failed");
case Warning:
case Assessment::Warning:
return xi18nc("@item:intable", "warning");
case Good:
case Assessment::Good:
return xi18nc("@item:intable", "good");
case NotApplicable:
case Assessment::NotApplicable:
default:
return xi18nc("@item:intable not applicable", "N/A");
}
}
static QString getPrettyValue(quint64 value, qint64 unit)
static QString getPrettyValue(quint64 value, SmartAttributeUnit unit)
{
QString rval;
switch (unit) {
case SK_SMART_ATTRIBUTE_UNIT_MSECONDS:
case SmartAttributeUnit::Miliseconds:
rval = KFormat().formatDuration(value);
break;
case SK_SMART_ATTRIBUTE_UNIT_SECTORS:
case SmartAttributeUnit::Sectors:
rval = xi18ncp("@item:intable", "%1 sector", "%1 sectors", value);
break;
case SK_SMART_ATTRIBUTE_UNIT_MKELVIN:
case SmartAttributeUnit::Milikelvin:
rval = SmartStatus::tempToString(value);
break;
case SK_SMART_ATTRIBUTE_UNIT_NONE:
case SmartAttributeUnit::None:
rval = QLocale().toString(value);
break;
case SK_SMART_ATTRIBUTE_UNIT_UNKNOWN:
case SmartAttributeUnit::Unknown:
default:
rval = xi18nc("@item:intable not applicable", "N/A");
break;
@ -214,43 +214,41 @@ static QString getAttrDescription(qint32 id)
return QString();
}
static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a)
static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a)
{
SmartAttribute::Assessment rval = SmartAttribute::NotApplicable;
SmartAttribute::Assessment rval = SmartAttribute::Assessment::NotApplicable;
bool failed = false;
bool hasFailed = false;
if (a->prefailure) {
if (a->good_now_valid && !a->good_now)
if (a.prefailure()) {
if (a.goodNowValid() && !a.goodNow())
failed = true;
if (a->good_in_the_past_valid && !a->good_in_the_past)
if (a.goodInThePastValid() && !a.goodInThePast())
hasFailed = true;
} else if (a->threshold_valid) {
if (a->current_value_valid && a->current_value <= a->threshold)
} else if (a.thresholdValid()) {
if (a.currentValueValid() && a.currentValue() <= a.threshold())
failed = true;
else if (a->worst_value_valid && a->worst_value <= a->threshold)
else if (a.worstValueValid() && a.worstValue() <= a.threshold())
hasFailed = true;
}
if (failed)
rval = SmartAttribute::Failing;
rval = SmartAttribute::Assessment::Failing;
else if (hasFailed)
rval = SmartAttribute::HasFailed;
else if (a->warn)
rval = SmartAttribute::Warning;
else if (a->good_now_valid)
rval = SmartAttribute::Good;
rval = SmartAttribute::Assessment::HasFailed;
else if (a.warn())
rval = SmartAttribute::Assessment::Warning;
else if (a.goodNowValid())
rval = SmartAttribute::Assessment::Good;
return rval;
}
static QString getRaw(const uint8_t* raw)
static QString getRaw(quint64 raw)
{
QString rval = QStringLiteral("0x");
for (qint32 i = 5; i >= 0; i--)
rval += QStringLiteral("%1").arg(raw[i], 2, 16, QLatin1Char('0'));
rval += QStringLiteral("%1").arg(raw, 12, 16, QLatin1Char('0'));
return rval;
}

View File

@ -15,30 +15,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_SMARTATTRIBUTE_H)
#ifndef KPMCORE_SMARTATTRIBUTE_H
#define KPMCORE_SMARTATTRIBUTE_H
#include "util/libpartitionmanagerexport.h"
#include <QString>
struct SkSmartAttributeParsedData;
class SmartAttributeParsedData;
class LIBKPMCORE_EXPORT SmartAttribute
{
public:
enum FailureType {
enum class FailureType {
PreFailure,
OldAge
};
enum UpdateType {
enum class UpdateType {
Online,
Offline
};
enum Assessment {
enum class Assessment {
NotApplicable,
Failing,
HasFailed,
@ -47,7 +46,7 @@ public:
};
public:
SmartAttribute(const SkSmartAttributeParsedData* a);
SmartAttribute(const SmartAttributeParsedData& a);
public:
qint32 id() const {
@ -104,4 +103,3 @@ private:
};
#endif

View File

@ -0,0 +1,644 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "smartattributeparseddata.h"
#include "core/smartdiskinformation.h"
#include <QJsonObject>
#include <QMap>
#include <QRegularExpression>
#include <QVariant>
#include <QVector>
#define MKELVIN_VALID_MIN ((qint64) ((-15LL*1000LL) + 273150LL))
#define MKELVIN_VALID_MAX ((qint64) ((100LL*1000LL) + 273150LL))
#define MSECOND_VALID_MIN 1ULL
#define MSECOND_VALID_SHORT_MAX (60ULL * 60ULL * 1000ULL)
#define MSECOND_VALID_LONG_MAX (30ULL * 365ULL * 24ULL * 60ULL * 60ULL * 1000ULL)
static QMap<qint32, SmartAttributeUnit> tableUnit();
static SmartQuirk getQuirk(QString model, QString firmware);
/** Creates a new SmartAttributeParsedData object.
@param disk the reference to the disk that this attribute is allocated to
@param jsonAttribute JSON attribute data
*/
SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk,
QJsonObject jsonAttribute) :
m_Id(0),
m_CurrentValue(0),
m_WorstValue(0),
m_Threshold(0),
m_Raw(0),
m_PrettyValue(0),
m_CurrentValueValid(false),
m_WorstValueValid(false),
m_ThresholdValid(false),
m_Prefailure(false),
m_Online(false),
m_GoodNow(true),
m_GoodNowValid(false),
m_GoodInThePast(true),
m_GoodInThePastValid(false),
m_Warn(false),
m_PrettyUnit(SmartAttributeUnit::Unknown),
m_Disk(disk),
m_Quirk(SmartQuirk::None)
{
if (disk)
m_Quirk = getQuirk(disk->model(), disk->firmware());
if (!jsonAttribute.isEmpty()) {
QString id = QStringLiteral("id");
QString value = QStringLiteral("value");
QString worst = QStringLiteral("worst");
QString thresh = QStringLiteral("thresh");
QString raw = QStringLiteral("raw");
QString flags = QStringLiteral("flags");
QString prefailure = QStringLiteral("prefailure");
QString online = QStringLiteral("updated_online");
m_Id = jsonAttribute[id].toInt();
m_CurrentValue = jsonAttribute[value].toInt();
m_WorstValue = jsonAttribute[worst].toInt();
m_Threshold = jsonAttribute[thresh].toInt();
QJsonObject rawObj = jsonAttribute[raw].toObject();
m_Raw = rawObj[value].toVariant().toULongLong();
QJsonObject flagsObj = jsonAttribute[flags].toObject();
m_Prefailure = flagsObj[prefailure].toBool();
m_Online = flagsObj[online].toBool();
if (!updateUnit())
m_PrettyUnit = SmartAttributeUnit::Unknown;
makePretty();
validateValues();
verifyAttribute();
}
}
/** @param other SmartAttributeParsedData to copy
*/
SmartAttributeParsedData::SmartAttributeParsedData(const SmartAttributeParsedData &other) :
m_Id(other.id()),
m_CurrentValue(other.currentValue()),
m_WorstValue(other.worstValue()),
m_Threshold(other.threshold()),
m_Raw(other.raw()),
m_PrettyValue(other.prettyValue()),
m_CurrentValueValid(other.currentValueValid()),
m_WorstValueValid(other.worstValueValid()),
m_ThresholdValid(other.thresholdValid()),
m_Prefailure(other.prefailure()),
m_Online(other.online()),
m_GoodNow(other.goodNow()),
m_GoodNowValid(other.goodNowValid()),
m_GoodInThePast(other.goodInThePast()),
m_GoodInThePastValid(other.goodInThePastValid()),
m_Warn(other.warn()),
m_PrettyUnit(other.prettyUnit()),
m_Disk(other.disk()),
m_Quirk(other.m_Quirk)
{
}
/** Validate values from the current attribute */
void SmartAttributeParsedData::validateValues()
{
m_CurrentValueValid = m_CurrentValue >= 1 && m_CurrentValue <= 0xFD;
m_WorstValueValid = m_WorstValue >= 1 && m_WorstValue <= 0xFD;
m_ThresholdValid = m_Threshold != 0xFE;
if (m_Threshold >= 1 && m_Threshold <= 0xFD) {
if (m_WorstValueValid) {
m_GoodInThePast = m_GoodInThePast && (m_WorstValue > m_Threshold);
m_GoodInThePastValid = true;
}
if (m_CurrentValueValid) {
m_GoodNow = m_GoodNow && (m_CurrentValue > m_Threshold);
m_GoodNowValid = true;
}
}
m_Warn = (m_GoodNowValid && !m_GoodNow) || (m_GoodInThePastValid && !m_GoodInThePast);
}
/** Make a pretty value from raw based on attribute's id */
void SmartAttributeParsedData::makePretty()
{
if (m_PrettyUnit == SmartAttributeUnit::Unknown)
return;
switch (id()) {
case 3:
m_PrettyValue = raw() & 0xFFFF;
break;
case 5:
m_PrettyValue = raw() & 0xFFFFFFFFU;
break;
case 9:
m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000;
break;
case 170:
m_PrettyValue = currentValue();
break;
case 190:
m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150;
break;
case 194:
m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150;
break;
case 197:
m_PrettyValue = (raw() & 0xFFFFFFFFU);
break;
case 222:
m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000;
break;
case 228:
m_PrettyValue = raw() * 60 * 1000;
break;
case 231:
m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150;
break;
case 232:
m_PrettyValue = currentValue();
break;
case 240:
m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000;
break;
case 241:
m_PrettyValue = raw() * 65536ULL * 512ULL / 1000000ULL;
break;
case 242:
m_PrettyValue = raw() * 65536ULL * 512ULL / 1000000ULL;
break;
default:
m_PrettyValue = raw();
break;
}
}
/** Verify attribute's unit */
void SmartAttributeParsedData::verifyAttribute()
{
if (id() == 3 || id() == 226)
verifyShortTime();
else if (id() == 5 || id() == 187 || id() == 197 || id() == 198)
verifySectors();
else if (id() == 9 || id() == 222 || id() == 240)
verifyLongTime();
else if (id() == 190 || id() == 194 || id() == 231)
verifyTemperature();
}
void SmartAttributeParsedData::verifyTemperature()
{
if (prettyUnit() != SmartAttributeUnit::Milikelvin)
return;
if (prettyValue() < MKELVIN_VALID_MIN || prettyValue() > MKELVIN_VALID_MAX)
m_PrettyUnit = SmartAttributeUnit::Unknown;
}
void SmartAttributeParsedData::verifyShortTime()
{
if (prettyUnit() != SmartAttributeUnit::Miliseconds)
return;
if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_SHORT_MAX)
m_PrettyUnit = SmartAttributeUnit::Unknown;
}
void SmartAttributeParsedData::verifyLongTime()
{
if (prettyUnit() != SmartAttributeUnit::Miliseconds)
return;
if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_LONG_MAX)
m_PrettyUnit = SmartAttributeUnit::Unknown;
}
void SmartAttributeParsedData::verifySectors()
{
if (prettyUnit() != SmartAttributeUnit::Sectors)
return;
quint64 maxSectors = disk()->size() / 512ULL;
if (prettyValue() == 0xFFFFFFFFULL || prettyValue() == 0xFFFFFFFFFFFFULL || (maxSectors > 0
&& prettyValue() > maxSectors))
m_PrettyUnit = SmartAttributeUnit::Unknown;
else if ((id() == 5 || id() == 197) && prettyValue() > 0)
m_Warn = true;
}
bool SmartAttributeParsedData::updateUnit()
{
if (m_Quirk) {
switch (id()) {
case 3:
if (m_Quirk & SmartQuirk::SMART_QUIRK_3_UNUSED) {
m_PrettyUnit = SmartAttributeUnit::Unknown;
return true;
}
break;
case 4:
if (m_Quirk & SmartQuirk::SMART_QUIRK_4_UNUSED) {
m_PrettyUnit = SmartAttributeUnit::Unknown;
return true;
}
break;
case 5:
if (m_Quirk & SmartQuirk::SMART_QUIRK_5_UNKNOWN)
return false;
break;
case 9:
if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONMINUTES) {
m_PrettyUnit = SmartAttributeUnit::Miliseconds;
return true;
} else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONSECONDS) {
m_PrettyUnit = SmartAttributeUnit::Miliseconds;
return true;
} else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES) {
m_PrettyUnit = SmartAttributeUnit::Miliseconds;
return true;
} else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_UNKNOWN)
return false;
break;
case 190:
if (m_Quirk & SmartQuirk::SMART_QUIRK_190_UNKNOWN)
return false;
break;
case 192:
if (m_Quirk & SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) {
m_PrettyUnit = SmartAttributeUnit::None;
return true;
}
break;
case 194:
if (m_Quirk & SmartQuirk::SMART_QUIRK_194_10XCELSIUS) {
m_PrettyUnit = SmartAttributeUnit::Milikelvin;
return true;
} else if (m_Quirk & SmartQuirk::SMART_QUIRK_194_UNKNOWN)
return false;
break;
case 197:
if (m_Quirk & SmartQuirk::SMART_QUIRK_197_UNKNOWN)
return false;
break;
case 198:
if (m_Quirk & SmartQuirk::SMART_QUIRK_198_UNKNOWN)
return false;
break;
case 200:
if (m_Quirk & SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT) {
m_PrettyUnit = SmartAttributeUnit::None;
return true;
}
break;
case 201:
if (m_Quirk & SmartQuirk::SMART_QUIRK_201_DETECTEDTACOUNT) {
m_PrettyUnit = SmartAttributeUnit::None;
return true;
}
break;
case 225:
if (m_Quirk & SmartQuirk::SMART_QUIRK_225_TOTALLBASWRITTEN) {
m_PrettyUnit = SmartAttributeUnit::MB;
return true;
}
break;
case 226:
if (m_Quirk & SmartQuirk::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) {
m_PrettyUnit = SmartAttributeUnit::SmallPercent;
return true;
}
break;
case 227:
if (m_Quirk & SmartQuirk::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) {
m_PrettyUnit = SmartAttributeUnit::SmallPercent;
return true;
}
break;
case 228:
if (m_Quirk & SmartQuirk::SMART_QUIRK_228_WORKLOADTIMER) {
m_PrettyUnit = SmartAttributeUnit::Miliseconds;
return true;
}
break;
case 232:
if (m_Quirk & SmartQuirk::SMART_QUIRK_232_AVAILABLERESERVEDSPACE) {
m_PrettyUnit = SmartAttributeUnit::Percent;
return true;
}
break;
case 233:
if (m_Quirk & SmartQuirk::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) {
m_PrettyUnit = SmartAttributeUnit::Percent;
return true;
}
break;
}
}
if (tableUnit().contains(id())) {
m_PrettyUnit = tableUnit()[id()];
return true;
}
return false;
}
static QMap<qint32, SmartAttributeUnit> tableUnit()
{
QMap<qint32, SmartAttributeUnit> table;
table.insert(1, SmartAttributeUnit::None);
table.insert(2, SmartAttributeUnit::Unknown);
table.insert(3, SmartAttributeUnit::Miliseconds);
table.insert(4, SmartAttributeUnit::None);
table.insert(5, SmartAttributeUnit::Sectors);
table.insert(6, SmartAttributeUnit::Unknown);
table.insert(7, SmartAttributeUnit::None);
table.insert(8, SmartAttributeUnit::Unknown);
table.insert(9, SmartAttributeUnit::Miliseconds);
table.insert(10, SmartAttributeUnit::None);
table.insert(11, SmartAttributeUnit::None);
table.insert(12, SmartAttributeUnit::None);
table.insert(13, SmartAttributeUnit::None);
table.insert(170, SmartAttributeUnit::Percent);
table.insert(171, SmartAttributeUnit::None);
table.insert(172, SmartAttributeUnit::None);
table.insert(175, SmartAttributeUnit::None);
table.insert(176, SmartAttributeUnit::None);
table.insert(177, SmartAttributeUnit::None);
table.insert(178, SmartAttributeUnit::None);
table.insert(179, SmartAttributeUnit::None);
table.insert(180, SmartAttributeUnit::None);
table.insert(181, SmartAttributeUnit::None);
table.insert(182, SmartAttributeUnit::None);
table.insert(183, SmartAttributeUnit::None);
table.insert(184, SmartAttributeUnit::None);
table.insert(187, SmartAttributeUnit::Sectors);
table.insert(188, SmartAttributeUnit::None);
table.insert(189, SmartAttributeUnit::None);
table.insert(190, SmartAttributeUnit::Milikelvin);
table.insert(191, SmartAttributeUnit::None);
table.insert(192, SmartAttributeUnit::None);
table.insert(193, SmartAttributeUnit::None);
table.insert(194, SmartAttributeUnit::Milikelvin);
table.insert(195, SmartAttributeUnit::None);
table.insert(196, SmartAttributeUnit::None);
table.insert(197, SmartAttributeUnit::Sectors);
table.insert(198, SmartAttributeUnit::Sectors);
table.insert(199, SmartAttributeUnit::None);
table.insert(200, SmartAttributeUnit::None);
table.insert(201, SmartAttributeUnit::None);
table.insert(202, SmartAttributeUnit::None);
table.insert(203, SmartAttributeUnit::Unknown);
table.insert(204, SmartAttributeUnit::None);
table.insert(205, SmartAttributeUnit::None);
table.insert(206, SmartAttributeUnit::Unknown);
table.insert(207, SmartAttributeUnit::Unknown);
table.insert(208, SmartAttributeUnit::Unknown);
table.insert(209, SmartAttributeUnit::Unknown);
table.insert(220, SmartAttributeUnit::Unknown);
table.insert(221, SmartAttributeUnit::None);
table.insert(222, SmartAttributeUnit::Miliseconds);
table.insert(223, SmartAttributeUnit::None);
table.insert(224, SmartAttributeUnit::Unknown);
table.insert(225, SmartAttributeUnit::None);
table.insert(226, SmartAttributeUnit::Miliseconds);
table.insert(227, SmartAttributeUnit::None);
table.insert(228, SmartAttributeUnit::None);
table.insert(230, SmartAttributeUnit::Unknown);
table.insert(231, SmartAttributeUnit::Milikelvin);
table.insert(232, SmartAttributeUnit::Percent);
table.insert(233, SmartAttributeUnit::Unknown);
table.insert(234, SmartAttributeUnit::Sectors);
table.insert(235, SmartAttributeUnit::Unknown);
table.insert(240, SmartAttributeUnit::Miliseconds);
table.insert(241, SmartAttributeUnit::MB);
table.insert(242, SmartAttributeUnit::MB);
table.insert(250, SmartAttributeUnit::None);
return table;
}
static const QVector<SmartAttributeParsedData::SmartQuirkDataBase> quirkDatabase()
{
typedef SmartAttributeParsedData::SmartQuirkDataBase QuirkDatabase;
QVector<QuirkDatabase> quirkDb;
quirkDb << QuirkDatabase(QStringLiteral("^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$"), QStringLiteral("^0085000B$"),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES |
SmartQuirk::SMART_QUIRK_197_UNKNOWN |
SmartQuirk::SMART_QUIRK_198_UNKNOWN));
quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHR2040AT$"), QStringLiteral(),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONSECONDS |
SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT |
SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT));
quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHS20[6432]0AT( .)?$"), QStringLiteral(),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONSECONDS |
SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT |
SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT |
SmartQuirk::SMART_QUIRK_201_DETECTEDTACOUNT));
quirkDb << QuirkDatabase(QStringLiteral("^("
"FUJITSU M1623TAU|"
"FUJITSU MHG2...ATU?.*|"
"FUJITSU MHH2...ATU?.*|"
"FUJITSU MHJ2...ATU?.*|"
"FUJITSU MHK2...ATU?.*|"
"FUJITSU MHL2300AT|"
"FUJITSU MHM2(20|15|10|06)0AT|"
"FUJITSU MHN2...AT|"
"FUJITSU MHR2020AT|"
"FUJITSU MHT2...(AH|AS|AT|BH)U?.*|"
"FUJITSU MHU2...ATU?.*|"
"FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*|"
"FUJITSU MP[A-G]3...A[HTEV]U?.*"
")$"),
QStringLiteral(),
SmartQuirk::SMART_QUIRK_9_POWERONSECONDS);
quirkDb << QuirkDatabase(QStringLiteral("^("
"SAMSUNG SV4012H|"
"SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]"
")$"),
QStringLiteral(),
SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
quirkDb << QuirkDatabase(QStringLiteral("^("
"SAMSUNG SV0412H|"
"SAMSUNG SV1204H"
")$"),
QStringLiteral(),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES | SmartQuirk::SMART_QUIRK_194_10XCELSIUS));
quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP40A2H$"),
QStringLiteral("^RR100-07$"),
SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP80A4H$"),
QStringLiteral("^RT100-06$"),
SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP8004H$"),
QStringLiteral("^QW100-61$"),
SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
quirkDb << QuirkDatabase(QStringLiteral("^("
"Maxtor 2B0(0[468]|1[05]|20)H1|"
"Maxtor 4G(120J6|160J[68])|"
"Maxtor 4D0(20H1|40H2|60H3|80H4)"
")$"),
QStringLiteral(),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | SmartQuirk::SMART_QUIRK_194_UNKNOWN));
quirkDb << QuirkDatabase(QStringLiteral("^("
"Maxtor 2F0[234]0[JL]0|"
"Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)|"
"Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)|"
"Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)|"
"Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)|"
"Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)|"
"Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)|"
"Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)|"
"Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)|"
"Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)|"
"Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)|"
"Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)|"
"Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)|"
"Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)|"
"Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)|"
"Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?|"
"Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)|"
"Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)|"
"Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)|"
"Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)|"
"Maxtor (98196H8|96147H6)|"
"Maxtor 4W(100H6|080H6|060H4|040H3|030H2)|"
"Maxtor 6(E0[234]|K04)0L0|"
"Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0|"
"Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)|"
"Maxtor 7Y250[PM]0|"
"Maxtor [45]A(25|30|32)0[JN]0|"
"Maxtor 7L(25|30)0[SR]0"
")$"),
QStringLiteral(),
SmartQuirk::SMART_QUIRK_9_POWERONMINUTES);
quirkDb << QuirkDatabase(QStringLiteral("^("
"HITACHI_DK14FA-20B|"
"HITACHI_DK23..-..B?|"
"HITACHI_DK23FA-20J|HTA422020F9AT[JN]0|"
"HE[JN]4230[23]0F9AT00|"
"HTC4260[23]0G5CE00|HTC4260[56]0G8CE00"
")$"),
QStringLiteral(),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | SmartQuirk::SMART_QUIRK_193_LOADUNLOAD));
quirkDb << QuirkDatabase(QStringLiteral("^HTS541010G9SA00$"),
QStringLiteral("^MBZOC60P$"),
SmartQuirk::SMART_QUIRK_5_UNKNOWN);
quirkDb << QuirkDatabase(QStringLiteral("^MCCOE64GEMPP$"),
QStringLiteral("^2.9.0[3-9]$"),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_5_UNKNOWN | SmartQuirk::SMART_QUIRK_190_UNKNOWN));
quirkDb << QuirkDatabase(QStringLiteral("^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$"),
QStringLiteral(),
static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_3_UNUSED |
SmartQuirk::SMART_QUIRK_4_UNUSED |
SmartQuirk::SMART_QUIRK_225_TOTALLBASWRITTEN |
SmartQuirk::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR |
SmartQuirk::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS |
SmartQuirk::SMART_QUIRK_228_WORKLOADTIMER |
SmartQuirk::SMART_QUIRK_232_AVAILABLERESERVEDSPACE |
SmartQuirk::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR));
return quirkDb;
}
static SmartQuirk getQuirk(QString model, QString firmware)
{
const QVector<SmartAttributeParsedData::SmartQuirkDataBase> db = quirkDatabase();
QRegularExpression modelRegex;
QRegularExpression firmwareRegex;
for (const SmartAttributeParsedData::SmartQuirkDataBase &item : qAsConst(db)) {
if (!item.model.isEmpty()) {
modelRegex.setPattern(item.model);
QRegularExpressionMatch match = modelRegex.match(model);
if (!match.hasMatch())
continue;
}
if (!item.firmware.isEmpty()) {
firmwareRegex.setPattern(item.firmware);
QRegularExpressionMatch match = firmwareRegex.match(firmware);
if (!match.hasMatch())
continue;
}
return item.quirk;
}
return SmartQuirk::None;
}

View File

@ -0,0 +1,225 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#ifndef KPMCORE_SMARTATTRIBUTEPARSEDDATA_H
#define KPMCORE_SMARTATTRIBUTEPARSEDDATA_H
#include <QJsonObject>
#include <QString>
class SmartDiskInformation;
/** SMART Quirk */
enum SmartQuirk {
None = 0x000000,
SMART_QUIRK_9_POWERONMINUTES = 0x000001,
SMART_QUIRK_9_POWERONSECONDS = 0x000002,
SMART_QUIRK_9_POWERONHALFMINUTES = 0x000004,
SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT = 0x000008,
SMART_QUIRK_193_LOADUNLOAD = 0x000010,
SMART_QUIRK_194_10XCELSIUS = 0x000020,
SMART_QUIRK_194_UNKNOWN = 0x000040,
SMART_QUIRK_200_WRITEERRORCOUNT = 0x000080,
SMART_QUIRK_201_DETECTEDTACOUNT = 0x000100,
SMART_QUIRK_5_UNKNOWN = 0x000200,
SMART_QUIRK_9_UNKNOWN = 0x000400,
SMART_QUIRK_197_UNKNOWN = 0x000800,
SMART_QUIRK_198_UNKNOWN = 0x001000,
SMART_QUIRK_190_UNKNOWN = 0x002000,
SMART_QUIRK_232_AVAILABLERESERVEDSPACE = 0x004000,
SMART_QUIRK_233_MEDIAWEAROUTINDICATOR = 0x008000,
SMART_QUIRK_225_TOTALLBASWRITTEN = 0x010000,
SMART_QUIRK_4_UNUSED = 0x020000,
SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR = 0x040000,
SMART_QUIRK_227_TIMEWORKLOADHOSTREADS = 0x080000,
SMART_QUIRK_228_WORKLOADTIMER = 0x100000,
SMART_QUIRK_3_UNUSED = 0x200000,
};
/** A unit for SMART attributes */
enum class SmartAttributeUnit {
Unknown,
None,
Miliseconds,
Sectors,
Milikelvin,
SmallPercent, /* percentage with 3 decimal points */
Percent,
MB,
};
/** A SMART parsed attribute.
It receives the attribute data from JSON, retrieve its data and validates its values.
@author Caio Carvalho <caiojcarvalho@gmail.com>
*/
class SmartAttributeParsedData
{
public:
/** SMART Quirk to some particular model and firmware */
struct SmartQuirkDataBase {
QString model;
QString firmware;
SmartQuirk quirk;
SmartQuirkDataBase(const QString &m = QString(),
const QString &f = QString(),
SmartQuirk q = SmartQuirk::None) :
model(m),
firmware(f),
quirk(q)
{
};
};
public:
SmartAttributeParsedData(SmartDiskInformation *disk, QJsonObject jsonAttribute);
SmartAttributeParsedData(const SmartAttributeParsedData &other);
public:
quint32 id() const
{
return m_Id; /**< @return attribute id */
}
qint32 currentValue() const
{
return m_CurrentValue; /**< @return attribute current value */
}
qint32 worstValue() const
{
return m_WorstValue; /**< @return attribute worst value */
}
qint32 threshold() const
{
return m_Threshold; /**< @return attribute threshold value */
}
bool prefailure() const
{
return m_Prefailure; /**< @return attribute prefailure status */
}
bool online() const
{
return m_Online; /**< @return attribute online status */
}
quint64 raw() const
{
return m_Raw; /**< @return attribute raw value */
}
quint64 prettyValue() const
{
return m_PrettyValue; /**< @return attribute pretty value */
}
SmartAttributeUnit prettyUnit() const
{
return m_PrettyUnit; /**< @return pretty unit value */
}
bool goodNowValid() const
{
return m_GoodNowValid; /**< @return good now attribute status validation */
}
bool goodNow() const
{
return m_GoodNow; /**< @return good now attribute status */
}
bool goodInThePastValid() const
{
return m_GoodInThePastValid; /**< @return good in the past attribute status validation */
}
bool goodInThePast() const
{
return m_GoodInThePast; /**< @return good in the past attribute status */
}
bool thresholdValid() const
{
return m_ThresholdValid; /**< @return threshold value validation */
}
bool currentValueValid() const
{
return m_CurrentValueValid; /**< @return current value validation */
}
bool worstValueValid() const
{
return m_WorstValueValid; /**< @return worst value validation */
}
bool warn() const
{
return m_Warn; /**< @return warn status */
}
SmartDiskInformation *disk() const
{
return m_Disk; /**< @return attribute's disk reference */
}
protected:
void validateValues();
bool updateUnit();
void makePretty();
void verifyAttribute();
void verifyTemperature();
void verifyShortTime();
void verifyLongTime();
void verifySectors();
private:
quint32 m_Id;
qint32 m_CurrentValue;
qint32 m_WorstValue;
qint32 m_Threshold;
quint64 m_Raw;
quint64 m_PrettyValue;
bool m_CurrentValueValid;
bool m_WorstValueValid;
bool m_ThresholdValid;
bool m_Prefailure;
bool m_Online;
bool m_GoodNow;
bool m_GoodNowValid;
bool m_GoodInThePast;
bool m_GoodInThePastValid;
bool m_Warn;
SmartAttributeUnit m_PrettyUnit;
SmartDiskInformation *m_Disk;
SmartQuirk m_Quirk;
};
#endif // SMARTATTRIBUTEPARSEDDATA_H

View File

@ -0,0 +1,198 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "core/smartdiskinformation.h"
#include "core/smartattributeparseddata.h"
#include <memory>
static quint64 u64log2(quint64 n);
/** Creates a new SmartDiskInformationObject */
SmartDiskInformation::SmartDiskInformation() :
m_ModelName(QString()),
m_FirmwareVersion(QString()),
m_SerialNumber(QString()),
m_Size(0),
m_Temperature(0),
m_BadSectors(0),
m_PoweredOn(0),
m_PowerCycles(0),
m_SmartStatus(false),
m_BadAttributeNow(false),
m_BadAttributeInThePast(false),
m_SelfTestExecutionStatus(SmartStatus::SelfTestStatus::Success),
m_Overall(SmartStatus::Overall::Bad)
{
}
/** Update the number of bad sectors based on reallocated sector count and current pending sector attributes data */
void SmartDiskInformation::updateBadSectors()
{
std::unique_ptr<SmartAttributeParsedData> reallocatedSectorCt(findAttribute(5));
std::unique_ptr<SmartAttributeParsedData> currentPendingSector(findAttribute(197));
if (!reallocatedSectorCt && !currentPendingSector)
m_BadSectors = 0;
else if (reallocatedSectorCt && currentPendingSector)
m_BadSectors = reallocatedSectorCt->prettyValue() + currentPendingSector->prettyValue();
else if (reallocatedSectorCt)
m_BadSectors = reallocatedSectorCt->prettyValue();
else
m_BadSectors = currentPendingSector->prettyValue();
}
/** Update SMART overall data based on the quantity of bad sectors and the status of SMART attributes */
void SmartDiskInformation::updateOverall()
{
if (!smartStatus()) {
m_Overall = SmartStatus::Overall::Bad;
return;
}
quint64 sector_threshold = u64log2(size() / 512) * 1024;
if (badSectors() >= sector_threshold) {
m_Overall = SmartStatus::Overall::BadSectorsMany;
return;
}
validateBadAttributes();
if (m_BadAttributeNow) {
m_Overall = SmartStatus::Overall::BadNow;
return;
}
if (badSectors() > 0) {
m_Overall = SmartStatus::Overall::BadSectors;
return;
}
if (m_BadAttributeInThePast) {
m_Overall = SmartStatus::Overall::BadPast;
return;
}
m_Overall = SmartStatus::Overall::Good;
}
/** Update the temperature value based on SMART attributes
@return a boolean representing the status of the operation
*/
bool SmartDiskInformation::updateTemperature()
{
std::unique_ptr<SmartAttributeParsedData> temperatureCelsius(findAttribute(231));
std::unique_ptr<SmartAttributeParsedData> temperatureCelsius2(findAttribute(194));
std::unique_ptr<SmartAttributeParsedData> airflowTemperatureCelsius(findAttribute(190));
if (temperatureCelsius != nullptr
&& temperatureCelsius->prettyUnit() == SmartAttributeUnit::Milikelvin) {
m_Temperature = temperatureCelsius->prettyValue();
return true;
} else if (temperatureCelsius2 != nullptr
&& temperatureCelsius2->prettyUnit() == SmartAttributeUnit::Milikelvin) {
m_Temperature = temperatureCelsius2->prettyValue();
return true;
} else if (airflowTemperatureCelsius != nullptr
&& airflowTemperatureCelsius->prettyUnit() ==
SmartAttributeUnit::Milikelvin) {
m_Temperature = airflowTemperatureCelsius->prettyValue();
return true;
}
return false;
}
/** Update the powered on value based on SMART attributes
@return a boolean representing the status of the operation
*/
bool SmartDiskInformation::updatePowerOn()
{
std::unique_ptr<SmartAttributeParsedData> powerOnHours(findAttribute(9));
std::unique_ptr<SmartAttributeParsedData> powerOnSeconds(findAttribute(233));
if (powerOnHours != nullptr
&& powerOnHours->prettyUnit() == SmartAttributeUnit::Miliseconds) {
m_PoweredOn = powerOnHours->prettyValue();
return true;
} else if (powerOnSeconds != nullptr
&& powerOnSeconds->prettyUnit() == SmartAttributeUnit::Miliseconds) {
m_PoweredOn = powerOnSeconds->prettyValue();
return true;
}
return false;
}
/** Update the power cycles value based on SMART attributes
@return a boolean representing the status of the operation
*/
bool SmartDiskInformation::updatePowerCycle()
{
std::unique_ptr<SmartAttributeParsedData> powerCycleCount(findAttribute(12));
if (powerCycleCount != nullptr
&& powerCycleCount->prettyUnit() == SmartAttributeUnit::None) {
m_PowerCycles = powerCycleCount->prettyValue();
return true;
}
return false;
}
/** Validate disk attributes status */
void SmartDiskInformation::validateBadAttributes()
{
for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) {
if (attribute.prefailure()) {
if (attribute.goodNowValid() && !attribute.goodNow())
m_BadAttributeNow = true;
if (attribute.goodInThePastValid() && !attribute.goodInThePast())
m_BadAttributeInThePast = true;
}
}
}
/** Search for a attribute based on its id number
@return a reference to the attribute
*/
SmartAttributeParsedData *SmartDiskInformation::findAttribute(quint32 id)
{
SmartAttributeParsedData *attr = nullptr;
for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) {
if (id == attribute.id()) {
attr = new SmartAttributeParsedData(attribute);
break;
}
}
return attr;
}
static quint64 u64log2(quint64 n)
{
quint64 r;
if (n <= 1)
return 0;
r = 0;
for (;;) {
n = n >> 1;
if (!n)
return r;
r++;
}
return 0;
}

View File

@ -0,0 +1,175 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#ifndef KPMCORE_SMARTDISKINFORMATION_H
#define KPMCORE_SMARTDISKINFORMATION_H
#include "core/smartstatus.h"
#include <QList>
#include <QString>
class SmartAttributeParsedData;
/** Disk information retrieved by SMART.
It includes a list with your SMART attributes.
@author Caio Carvalho <caiojcarvalho@gmail.com>
*/
class SmartDiskInformation
{
public:
SmartDiskInformation();
public:
void updateBadSectors();
void updateOverall();
bool updateTemperature();
bool updatePowerOn();
bool updatePowerCycle();
SmartAttributeParsedData *findAttribute(quint32 id);
public:
const QString model() const
{
return m_ModelName; /**< @return the disk model name */
}
const QString firmware() const
{
return m_FirmwareVersion; /**< @return the disk firmware version */
}
const QString serial() const
{
return m_SerialNumber; /**< @return the disk serial number */
}
quint64 size() const
{
return m_Size; /**< @return disk size */
}
bool smartStatus() const
{
return m_SmartStatus; /**< @return a boolean representing SMART status */
}
SmartStatus::SelfTestStatus selfTestExecutionStatus() const
{
return m_SelfTestExecutionStatus; /**< @return SMART self execution status */
}
SmartStatus::Overall overall() const
{
return m_Overall; /**< @return SMART overall status */
}
quint64 temperature() const
{
return m_Temperature; /**< @return disk temperature in kelvin */
}
quint64 badSectors() const
{
return m_BadSectors; /**< @return the number of bad sectors */
}
quint64 poweredOn() const
{
return m_PoweredOn; /**< @return quantity of time that device is powered on */
}
quint64 powerCycles() const
{
return m_PowerCycles; /**< @return quantity of power cycles */
}
QList<SmartAttributeParsedData> attributes() const
{
return m_Attributes; /**< @return a list that contains the disk SMART attributes */
}
public:
void setModel(QString modelName)
{
m_ModelName = modelName;
}
void setFirmware(QString firmware)
{
m_FirmwareVersion = firmware;
}
void setSerial(QString serial)
{
m_SerialNumber = serial;
}
void setSize(quint64 size)
{
m_Size = size;
}
void setPowerCycles(quint64 powerCycleCt)
{
m_PowerCycles = powerCycleCt;
}
void setSmartStatus(bool smartStatus)
{
m_SmartStatus = smartStatus;
}
void setSelfTestExecutionStatus(SmartStatus::SelfTestStatus status)
{
m_SelfTestExecutionStatus = status;
}
void addAttribute(SmartAttributeParsedData &attribute)
{
m_Attributes << attribute;
}
protected:
void validateBadAttributes();
private:
QString m_ModelName;
QString m_FirmwareVersion;
QString m_SerialNumber;
quint64 m_Size;
quint64 m_Temperature;
quint64 m_BadSectors;
quint64 m_PoweredOn;
quint64 m_PowerCycles;
bool m_SmartStatus;
bool m_BadAttributeNow;
bool m_BadAttributeInThePast;
SmartStatus::SelfTestStatus m_SelfTestExecutionStatus;
SmartStatus::Overall m_Overall;
QList<SmartAttributeParsedData> m_Attributes;
};
#endif // SMARTDISKINFORMATION_H

161
src/core/smartparser.cpp Normal file
View File

@ -0,0 +1,161 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "core/smartparser.h"
#include "core/smartattributeparseddata.h"
#include "core/smartdiskinformation.h"
#include "util/externalcommand.h"
#include <errno.h>
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QString>
/** Creates a new SmartParser object
@param device_path device path that indicates the device that SMART must analyse
*/
SmartParser::SmartParser(const QString &device_path) :
m_DevicePath(device_path),
m_DiskInformation(nullptr)
{
}
SmartParser::~SmartParser()
{
delete m_DiskInformation;
}
/** Initialize SmartParser data, retrieve the information from SMART JSON and initialize the disk information data */
bool SmartParser::init()
{
loadSmartOutput();
if (m_SmartOutput.isEmpty())
return false;
QJsonObject smartJson = m_SmartOutput.object();
QString model_name = QStringLiteral("model_name");
QString firmware = QStringLiteral("firmware_version");
QString serial_number = QStringLiteral("serial_number");
QString device = QStringLiteral("device");
QString smart_status = QStringLiteral("smart_status");
QString passed = QStringLiteral("passed");
QString self_test = QStringLiteral("self_test");
QString status = QStringLiteral("status");
QString value = QStringLiteral("value");
QString user_capacity = QStringLiteral("user_capacity");
if (!smartJson.contains(device)) {
qDebug() << "smart disk open failed for " << devicePath() << ": " << strerror(errno);
return false;
}
if (!smartJson.contains(smart_status)) {
qDebug() << "getting smart status failed for " << devicePath() << ": " << strerror(errno);
return false;
}
if (!smartJson.contains(model_name) || !smartJson.contains(firmware)
|| !smartJson.contains(serial_number)) {
qDebug() << "getting disk identification data failed for " << devicePath() << ": " << strerror(
errno);
return false;
}
m_DiskInformation = new SmartDiskInformation();
QJsonObject smartStatus = smartJson[smart_status].toObject();
m_DiskInformation->setSmartStatus(smartStatus[passed].toBool());
m_DiskInformation->setModel(smartJson[model_name].toString());
m_DiskInformation->setFirmware(smartJson[firmware].toString());
m_DiskInformation->setSerial(smartJson[serial_number].toString());
m_DiskInformation->setSize(smartJson[user_capacity].toVariant().toULongLong());
QJsonObject selfTest = smartJson[self_test].toObject();
QJsonObject selfTestStatus = selfTest[status].toObject();
m_DiskInformation->setSelfTestExecutionStatus(static_cast<SmartStatus::SelfTestStatus>(selfTestStatus[value].toInt()));
loadAttributes();
m_DiskInformation->updateBadSectors();
m_DiskInformation->updateOverall();
if (!m_DiskInformation->updateTemperature())
qDebug() << "getting temp failed for " << devicePath() << ": " << strerror(errno);
if (!m_DiskInformation->updatePowerOn())
qDebug() << "getting powered on time failed for " << devicePath() << ": " << strerror(errno);
if (!m_DiskInformation->updatePowerCycle())
qDebug() << "getting power cycles failed for " << devicePath() << ": " << strerror(errno);
return true;
}
/** Run smartctl command and recover its output */
void SmartParser::loadSmartOutput()
{
if (m_SmartOutput.isEmpty()) {
ExternalCommand smartctl(QStringLiteral("smartctl"), { QStringLiteral("--all"), QStringLiteral("--json"), devicePath() });
if (smartctl.run() && smartctl.exitCode() == 0) {
QByteArray output = smartctl.rawOutput();
m_SmartOutput = QJsonDocument::fromJson(output);
}
else
qDebug() << "smartctl initialization failed for " << devicePath() << ": " << strerror(errno);
}
}
/** Load SMART disk attributes from JSON data */
void SmartParser::loadAttributes()
{
loadSmartOutput();
if (m_SmartOutput.isEmpty())
return;
QJsonObject smartJson = m_SmartOutput.object();
QString ata_smart_attributes = QStringLiteral("ata_smart_attributes");
QString table = QStringLiteral("table");
QJsonObject ataSmartAttributes = smartJson[ata_smart_attributes].toObject();
QJsonArray attributeArray = ataSmartAttributes[table].toArray();
if (!m_DiskInformation) {
qDebug() << "error loading smart attributes for " << devicePath() << ": " << strerror(errno);
return;
}
for (const QJsonValue &value : qAsConst(attributeArray)) {
SmartAttributeParsedData parsedObject(m_DiskInformation, value.toObject());
m_DiskInformation->addAttribute(parsedObject);
}
}

View File

@ -1,5 +1,5 @@
/*************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -15,48 +15,50 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_LIBPARTEDDEVICE_H)
#ifndef KPMCORE_SMARTPARSER_H
#define KPMCORE_SMARTPARSER_H
#define KPMCORE_LIBPARTEDDEVICE_H
#include <QJsonDocument>
#include <QString>
#include "backend/corebackenddevice.h"
class SmartDiskInformation;
#include <QtGlobal>
/** A parser to SMART JSON output.
#include <parted/parted.h>
Responsible to execute smartctl and parse its output.
class Partition;
class PartitionTable;
class Report;
class CoreBackendPartitionTable;
class LibPartedDevice : public CoreBackendDevice
@author Caio Carvalho <caiojcarvalho@gmail.com>
*/
class SmartParser
{
Q_DISABLE_COPY(LibPartedDevice)
public:
SmartParser(const QString &device_path);
~SmartParser();
public:
LibPartedDevice(const QString& deviceNode);
~LibPartedDevice();
bool init();
public:
bool open() override;
bool openExclusive() override;
bool close() override;
CoreBackendPartitionTable* openPartitionTable() override;
bool createPartitionTable(Report& report, const PartitionTable& ptable) override;
bool readData(QByteArray& buffer, qint64 offset, qint64 size) override;
bool writeData(QByteArray& buffer, qint64 offset) override;
protected:
PedDevice* pedDevice() {
return m_PedDevice;
const QString &devicePath() const
{
return m_DevicePath; /**< @return the device path that SMART must analyse */
}
SmartDiskInformation *diskInformation() const
{
return m_DiskInformation; /**< @return a reference to parsed disk information */
}
protected:
void loadSmartOutput();
void loadAttributes();
private:
PedDevice* m_PedDevice;
const QString m_DevicePath;
QJsonDocument m_SmartOutput;
SmartDiskInformation *m_DiskInformation;
};
#endif
#endif // SMARTPARSER_H

View File

@ -18,24 +18,27 @@
#include "core/smartstatus.h"
#include "core/smartparser.h"
#include "core/smartdiskinformation.h"
#include "core/smartattributeparseddata.h"
#include <KLocalizedString>
#include <QDebug>
#include <QString>
#include <QStringList>
#include <atasmart.h>
#include <errno.h>
SmartStatus::SmartStatus(const QString& device_path) :
SmartStatus::SmartStatus(const QString &device_path) :
m_DevicePath(device_path),
m_InitSuccess(false),
m_Status(false),
m_ModelName(),
m_Serial(),
m_Firmware(),
m_Overall(Bad),
m_SelfTestStatus(Success),
m_Overall(Overall::Bad),
m_SelfTestStatus(SelfTestStatus::Success),
m_Temp(0),
m_BadSectors(0),
m_PowerCycles(0),
@ -46,148 +49,31 @@ SmartStatus::SmartStatus(const QString& device_path) :
void SmartStatus::update()
{
SkDisk* skDisk = nullptr;
SkBool skSmartStatus = false;
uint64_t mkelvin = 0;
uint64_t skBadSectors = 0;
uint64_t skPoweredOn = 0;
uint64_t skPowerCycles = 0;
SmartParser parser(devicePath());
if (sk_disk_open(devicePath().toLocal8Bit().constData(), &skDisk) < 0) {
qDebug() << "smart disk open failed for " << devicePath() << ": " << strerror(errno);
if (!parser.init()) {
qDebug() << "error during smart output parsing for " << devicePath() << ": " << strerror(errno);
return;
}
if (sk_disk_smart_status(skDisk, &skSmartStatus) < 0) {
qDebug() << "getting smart status failed for " << devicePath() << ": " << strerror(errno);
sk_disk_free(skDisk);
SmartDiskInformation *disk;
disk = parser.diskInformation();
if (!disk)
return;
}
setStatus(skSmartStatus);
if (sk_disk_smart_read_data(skDisk) < 0) {
qDebug() << "reading smart data failed for " << devicePath() << ": " << strerror(errno);
sk_disk_free(skDisk);
return;
}
const SkIdentifyParsedData* skIdentify;
if (sk_disk_identify_parse(skDisk, &skIdentify) < 0)
qDebug() << "getting identify data failed for " << devicePath() << ": " << strerror(errno);
else {
setModelName(QString::fromLocal8Bit(skIdentify->model));
setFirmware(QString::fromLocal8Bit(skIdentify->firmware));
setSerial(QString::fromLocal8Bit(skIdentify->serial));
}
const SkSmartParsedData* skParsed;
if (sk_disk_smart_parse(skDisk, &skParsed) < 0)
qDebug() << "parsing disk smart data failed for " << devicePath() << ": " << strerror(errno);
else {
switch (skParsed->self_test_execution_status) {
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ABORTED:
setSelfTestStatus(Aborted);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED:
setSelfTestStatus(Interrupted);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_FATAL:
setSelfTestStatus(Fatal);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN:
setSelfTestStatus(ErrorUnknown);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL:
setSelfTestStatus(ErrorEletrical);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO:
setSelfTestStatus(ErrorServo);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ:
setSelfTestStatus(ErrorRead);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING:
setSelfTestStatus(ErrorHandling);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS:
setSelfTestStatus(InProgress);
break;
default:
case SK_SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER:
setSelfTestStatus(Success);
break;
}
}
SkSmartOverall overall;
if (sk_disk_smart_get_overall(skDisk, &overall) < 0)
qDebug() << "getting status failed for " << devicePath() << ": " << strerror(errno);
else {
switch (overall) {
case SK_SMART_OVERALL_GOOD:
setOverall(Good);
break;
case SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST:
setOverall(BadPast);
break;
case SK_SMART_OVERALL_BAD_SECTOR:
setOverall(BadSectors);
break;
case SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW:
setOverall(BadNow);
break;
case SK_SMART_OVERALL_BAD_SECTOR_MANY:
setOverall(BadSectorsMany);
break;
default:
case SK_SMART_OVERALL_BAD_STATUS:
setOverall(Bad);
break;
}
}
if (sk_disk_smart_get_temperature(skDisk, &mkelvin) < 0)
qDebug() << "getting temp failed for " << devicePath() << ": " << strerror(errno);
else
setTemp(mkelvin);
if (sk_disk_smart_get_bad(skDisk, &skBadSectors) < 0)
qDebug() << "getting bad sectors failed for " << devicePath() << ": " << strerror(errno);
else
setBadSectors(skBadSectors);
if (sk_disk_smart_get_power_on(skDisk, &skPoweredOn) < 0)
qDebug() << "getting powered on time failed for " << devicePath() << ": " << strerror(errno);
else
setPoweredOn(skPoweredOn);
if (sk_disk_smart_get_power_cycle(skDisk, &skPowerCycles) < 0)
qDebug() << "getting power cycles failed for " << devicePath() << ": " << strerror(errno);
else
setPowerCycles(skPowerCycles);
m_Attributes.clear();
sk_disk_smart_parse_attributes(skDisk, callback, this);
sk_disk_free(skDisk);
setStatus(disk->smartStatus());
setModelName(disk->model());
setFirmware(disk->firmware());
setSerial(disk->serial());
setSelfTestStatus(disk->selfTestExecutionStatus());
setOverall(disk->overall());
setTemp(disk->temperature());
setBadSectors(disk->badSectors());
setPoweredOn(disk->poweredOn());
setPowerCycles(disk->powerCycles());
addAttributes(disk->attributes());
setInitSuccess(true);
}
@ -195,40 +81,41 @@ QString SmartStatus::tempToString(quint64 mkelvin)
{
const double celsius = (mkelvin - 273150.0) / 1000.0;
const double fahrenheit = 9.0 * celsius / 5.0 + 32;
return xi18nc("@item:intable degrees in Celsius and Fahrenheit", "%1° C / %2° F", QLocale().toString(celsius, 1), QLocale().toString(fahrenheit, 1));
return xi18nc("@item:intable degrees in Celsius and Fahrenheit", "%1° C / %2° F",
QLocale().toString(celsius, 1), QLocale().toString(fahrenheit, 1));
}
QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s)
{
switch (s) {
case Aborted:
case SelfTestStatus::Aborted:
return xi18nc("@item", "Aborted");
case Interrupted:
case SelfTestStatus::Interrupted:
return xi18nc("@item", "Interrupted");
case Fatal:
case SelfTestStatus::Fatal:
return xi18nc("@item", "Fatal error");
case ErrorUnknown:
case SelfTestStatus::ErrorUnknown:
return xi18nc("@item", "Unknown error");
case ErrorEletrical:
case SelfTestStatus::ErrorEletrical:
return xi18nc("@item", "Electrical error");
case ErrorServo:
case SelfTestStatus::ErrorServo:
return xi18nc("@item", "Servo error");
case ErrorRead:
case SelfTestStatus::ErrorRead:
return xi18nc("@item", "Read error");
case ErrorHandling:
case SelfTestStatus::ErrorHandling:
return xi18nc("@item", "Handling error");
case InProgress:
case SelfTestStatus::InProgress:
return xi18nc("@item", "Self test in progress");
case Success:
case SelfTestStatus::Success:
default:
return xi18nc("@item", "Success");
}
@ -238,33 +125,35 @@ QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s)
QString SmartStatus::overallAssessmentToString(Overall o)
{
switch (o) {
case Good:
case Overall::Good:
return xi18nc("@item", "Healthy");
case BadPast:
case Overall::BadPast:
return xi18nc("@item", "Has been used outside of its design parameters in the past.");
case BadSectors:
case Overall::BadSectors:
return xi18nc("@item", "Has some bad sectors.");
case BadNow:
case Overall::BadNow:
return xi18nc("@item", "Is being used outside of its design parameters right now.");
case BadSectorsMany:
case Overall::BadSectorsMany:
return xi18nc("@item", "Has many bad sectors.");
case Bad:
case Overall::Bad:
default:
return xi18nc("@item", "Disk failure is imminent. Backup all data!");
}
}
void SmartStatus::callback(SkDisk*, const SkSmartAttributeParsedData* a, void* user_data)
void SmartStatus::addAttributes(QList<SmartAttributeParsedData> attr)
{
SmartStatus* self = reinterpret_cast<SmartStatus*>(user_data);
m_Attributes.clear();
SmartAttribute sm(a);
self->m_Attributes.append(sm);
for (const SmartAttributeParsedData &at : qAsConst(attr)) {
SmartAttribute sm(at);
m_Attributes.append(sm);
}
}

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_SMARTSTATUS_H)
#ifndef KPMCORE_SMARTSTATUS_H
#define KPMCORE_SMARTSTATUS_H
#include "util/libpartitionmanagerexport.h"
@ -32,7 +31,7 @@ struct SkDisk;
class LIBKPMCORE_EXPORT SmartStatus
{
public:
enum Overall {
enum class Overall {
Good,
BadPast,
BadSectors,
@ -41,7 +40,7 @@ public:
Bad
};
enum SelfTestStatus {
enum class SelfTestStatus {
Success,
Aborted,
Interrupted,
@ -51,99 +50,123 @@ public:
ErrorServo,
ErrorRead,
ErrorHandling,
InProgress
InProgress = 15,
};
public:
typedef QList<SmartAttribute> Attributes;
public:
SmartStatus(const QString& device_path);
SmartStatus(const QString &device_path);
public:
void update();
const QString& devicePath() const {
const QString &devicePath() const
{
return m_DevicePath;
}
bool isValid() const {
bool isValid() const
{
return m_InitSuccess;
}
bool status() const {
bool status() const
{
return m_Status;
}
const QString& modelName() const {
const QString &modelName() const
{
return m_ModelName;
}
const QString& serial() const {
const QString &serial() const
{
return m_Serial;
}
const QString& firmware() const {
const QString &firmware() const
{
return m_Firmware;
}
quint64 temp() const {
quint64 temp() const
{
return m_Temp;
}
quint64 badSectors() const {
quint64 badSectors() const
{
return m_BadSectors;
}
quint64 powerCycles() const {
quint64 powerCycles() const
{
return m_PowerCycles;
}
quint64 poweredOn() const {
quint64 poweredOn() const
{
return m_PoweredOn;
}
const Attributes& attributes() const {
const Attributes &attributes() const
{
return m_Attributes;
}
Overall overall() const {
Overall overall() const
{
return m_Overall;
}
SelfTestStatus selfTestStatus() const {
SelfTestStatus selfTestStatus() const
{
return m_SelfTestStatus;
}
void addAttributes(QList<SmartAttributeParsedData> attr);
static QString tempToString(quint64 mkelvin);
static QString overallAssessmentToString(Overall o);
static QString selfTestStatusToString(SmartStatus::SelfTestStatus s);
protected:
void setStatus(bool s) {
private:
void setStatus(bool s)
{
m_Status = s;
}
void setModelName(const QString& name) {
void setModelName(const QString &name)
{
m_ModelName = name;
}
void setSerial(const QString& s) {
void setSerial(const QString &s)
{
m_Serial = s;
}
void setFirmware(const QString& f) {
void setFirmware(const QString &f)
{
m_Firmware = f;
}
void setTemp(quint64 t) {
void setTemp(quint64 t)
{
m_Temp = t;
}
void setInitSuccess(bool b) {
void setInitSuccess(bool b)
{
m_InitSuccess = b;
}
void setBadSectors(quint64 s) {
void setBadSectors(quint64 s)
{
m_BadSectors = s;
}
void setPowerCycles(quint64 p) {
void setPowerCycles(quint64 p)
{
m_PowerCycles = p;
}
void setPoweredOn(quint64 t) {
void setPoweredOn(quint64 t)
{
m_PoweredOn = t;
}
void setOverall(Overall o) {
void setOverall(Overall o)
{
m_Overall = o;
}
void setSelfTestStatus(SelfTestStatus s) {
void setSelfTestStatus(SelfTestStatus s)
{
m_SelfTestStatus = s;
}
static void callback(SkDisk* skDisk, const SkSmartAttributeParsedData* a, void* user_data);
private:
const QString m_DevicePath;
bool m_InitSuccess;

View File

@ -1,5 +1,6 @@
/*************************************************************************
* Copyright (C) 2016 by Chantara Tith <tith.chantara@gmail.com> *
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -15,18 +16,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "core/device_p.h"
#include "core/volumemanagerdevice.h"
#include "core/volumemanagerdevice_p.h"
/** Constructs an abstract Volume Manager Device with an empty PartitionTable.
*
* @param name the Device's name
* @param deviceNode the Device's node
* @param logicalExtentSize the logical extent size that device uses
*/
VolumeManagerDevice::VolumeManagerDevice(const QString& name,
VolumeManagerDevice::VolumeManagerDevice(std::shared_ptr<VolumeManagerDevicePrivate> d,
const QString& name,
const QString& deviceNode,
const qint64 logicalSize,
const qint64 logicalExtentSize,
const qint64 totalLogical,
const QString& iconName,
Device::Type type)
: Device(name, deviceNode, logicalSize, totalLogical, iconName, type)
: Device(std::static_pointer_cast<DevicePrivate>(d), name, deviceNode, logicalExtentSize, totalLogical, iconName, type)
{
}
@ -34,3 +41,9 @@ QString VolumeManagerDevice::prettyDeviceNodeList() const
{
return deviceNodes().join(QStringLiteral(", "));
}
void VolumeManagerDevice::setTotalLogical(qint64 n)
{
Q_ASSERT(n > 0);
d->m_TotalLogical = n;
}

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_VOLUMEMANAGERDEVICE_H)
#ifndef KPMCORE_VOLUMEMANAGERDEVICE_H
#define KPMCORE_VOLUMEMANAGERDEVICE_H
#include "util/libpartitionmanagerexport.h"
@ -27,6 +26,8 @@
#include <QObject>
#include <QtGlobal>
class VolumeManagerDevicePrivate;
/** A Volume Manager of physical devices represented as an abstract device.
*
* VolumeManagerDevice is an abstract device class for volume manager. e.g: LVM, SoftRAID.
@ -41,8 +42,7 @@ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device
Q_DISABLE_COPY(VolumeManagerDevice)
public:
VolumeManagerDevice(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device);
VolumeManagerDevice(std::shared_ptr<VolumeManagerDevicePrivate> d, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Type::Unknown_Device);
/**
* @return list of physical device's path that makes up volumeManagerDevice.(e.g: /dev/sda, /dev/sdb1)
@ -52,7 +52,7 @@ public:
/**
* @return list of logical partition's path.
*/
virtual const QStringList partitionNodes() const = 0;
virtual const QStringList& partitionNodes() const = 0;
/**
* @return size of logical partition at the given path in bytes.
@ -76,13 +76,13 @@ protected:
* @sector sector value to be mapped (if 0, will return start sector of the partition)
* @return absolute sector value as represented inside device's partitionTable
*/
virtual qint64 mappedSector(const QString& partitionPath, qint64 sector) const = 0;
virtual qint64 mappedSector(const QString& partitionPath, qint64 sector) const = 0;
public:
/** string deviceNodes together into comma-sperated list
/** join deviceNodes together into comma-separated list
*
* @return comma-seperated list of deviceNodes
* @return comma-separated list of deviceNodes
*/
virtual QString prettyDeviceNodeList() const;
@ -90,10 +90,7 @@ public:
*
* @param n Number of sectors.
*/
void setTotalLogical(qint64 n) {
Q_ASSERT(n > 0);
m_TotalLogical = n;
}
void setTotalLogical(qint64 n);
};
#endif

View File

@ -0,0 +1,27 @@
/*************************************************************************
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#ifndef KPMCORE_VOLUMEMANAGERDEVICE_P_H
#define KPMCORE_VOLUMEMANAGERDEVICE_P_H
#include "core/device_p.h"
class VolumeManagerDevicePrivate : public DevicePrivate
{
};
#endif

View File

@ -16,6 +16,7 @@ set(FS_SRC
fs/hpfs.cpp
fs/iso9660.cpp
fs/jfs.cpp
fs/linuxraidmember.cpp
fs/linuxswap.cpp
fs/luks.cpp
fs/luks2.cpp
@ -51,6 +52,7 @@ set(FS_LIB_HDRS
fs/hpfs.h
fs/iso9660.h
fs/jfs.h
fs/linuxraidmember.h
fs/linuxswap.h
fs/luks.h
fs/luks2.h

View File

@ -44,7 +44,7 @@ FileSystem::CommandSupportType btrfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType btrfs::m_GetUUID = FileSystem::cmdSupportNone;
btrfs::btrfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Btrfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Btrfs)
{
}
@ -91,12 +91,12 @@ FileSystem::SupportTool btrfs::supportToolName() const
qint64 btrfs::minCapacity() const
{
return 256 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 256 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 btrfs::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
int btrfs::maxLabelLength() const

View File

@ -39,7 +39,7 @@ FileSystem::CommandSupportType exfat::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType exfat::m_GetUUID = FileSystem::cmdSupportNone;
exfat::exfat(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Exfat)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Exfat)
{
}
@ -84,7 +84,7 @@ FileSystem::SupportTool exfat::supportToolName() const
qint64 exfat::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
int exfat::maxLabelLength() const
@ -112,8 +112,8 @@ bool exfat::writeLabel(Report& report, const QString& deviceNode, const QString&
bool exfat::updateUUID(Report& report, const QString& deviceNode) const
{
Q_UNUSED(report);
Q_UNUSED(deviceNode);
Q_UNUSED(report)
Q_UNUSED(deviceNode)
return false;
}

View File

@ -84,7 +84,7 @@ FileSystem::SupportTool ext2::supportToolName() const
qint64 ext2::maxCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
int ext2::maxLabelLength() const

View File

@ -37,7 +37,7 @@ namespace FS
class LIBKPMCORE_EXPORT ext2 : public FileSystem
{
public:
ext2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Ext2);
ext2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Ext2);
public:
void init() override;

View File

@ -25,13 +25,13 @@
namespace FS
{
ext3::ext3(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
ext2(firstsector, lastsector, sectorsused, label, FileSystem::Ext3)
ext2(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ext3)
{
}
qint64 ext3::maxCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
bool ext3::create(Report& report, const QString& deviceNode)

View File

@ -25,13 +25,13 @@
namespace FS
{
ext4::ext4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
ext2(firstsector, lastsector, sectorsused, label, FileSystem::Ext4)
ext2(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ext4)
{
}
qint64 ext4::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
bool ext4::create(Report& report, const QString& deviceNode)

View File

@ -25,7 +25,7 @@ FileSystem::CommandSupportType extended::m_Shrink = FileSystem::cmdSupportCore;
FileSystem::CommandSupportType extended::m_Move = FileSystem::cmdSupportCore;
extended::extended(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Extended)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Extended)
{
}

View File

@ -46,7 +46,7 @@ FileSystem::CommandSupportType f2fs::m_GetUUID = FileSystem::cmdSupportNone;
bool f2fs::oldVersion = false; // 1.8.x or older
f2fs::f2fs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::F2fs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::F2fs)
{
}
@ -100,12 +100,12 @@ FileSystem::SupportTool f2fs::supportToolName() const
qint64 f2fs::minCapacity() const
{
return 30 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 30 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 f2fs::maxCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB);
}
int f2fs::maxLabelLength() const

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_F2FS_H)
#ifndef KPMCORE_F2FS_H
#define KPMCORE_F2FS_H
#include "util/libpartitionmanagerexport.h"

View File

@ -87,12 +87,12 @@ FileSystem::SupportTool fat12::supportToolName() const
qint64 fat12::minCapacity() const
{
return 1 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 1 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 fat12::maxCapacity() const
{
return 255 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 255 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
int fat12::maxLabelLength() const
@ -167,12 +167,7 @@ bool fat12::updateUUID(Report& report, const QString& deviceNode) const
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") });
if (!cmd.start())
return false;
if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid))
return false;
return cmd.waitFor(-1);
cmd.write(QByteArray(uuid, sizeof(uuid)));
return cmd.start();
}
}

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_FAT12_H)
#ifndef KPMCORE_FAT12_H
#define KPMCORE_FAT12_H
#include "util/libpartitionmanagerexport.h"
@ -38,7 +37,7 @@ namespace FS
class LIBKPMCORE_EXPORT fat12 : public FileSystem
{
public:
fat12(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Fat12);
fat12(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Fat12);
public:
void init() override;
@ -62,10 +61,10 @@ public:
return m_Create;
}
CommandSupportType supportGrow() const override {
return m_Grow;
return cmdSupportNone;
}
CommandSupportType supportShrink() const override {
return m_Shrink;
return cmdSupportNone;
}
CommandSupportType supportMove() const override {
return m_Move;

View File

@ -33,7 +33,7 @@
namespace FS
{
fat16::fat16(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
fat12(firstsector, lastsector, sectorsused, label, FileSystem::Fat16)
fat12(firstsector, lastsector, sectorsused, label, FileSystem::Type::Fat16)
{
}
@ -75,12 +75,12 @@ bool fat16::supportToolFound() const
qint64 fat16::minCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 fat16::maxCapacity() const
{
return 4 * Capacity::unitFactor(Capacity::Byte, Capacity::GiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 4 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::GiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
bool fat16::create(Report& report, const QString& deviceNode)

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_FAT16_H)
#ifndef KPMCORE_FAT16_H
#define KPMCORE_FAT16_H
#include "fs/fat12.h"
@ -43,6 +42,13 @@ public:
bool create(Report& report, const QString& deviceNode) override;
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
CommandSupportType supportGrow() const override {
return m_Grow;
}
CommandSupportType supportShrink() const override {
return m_Shrink;
}
qint64 minCapacity() const override;
qint64 maxCapacity() const override;
bool supportToolFound() const override;

View File

@ -26,18 +26,18 @@
namespace FS
{
fat32::fat32(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
fat16(firstsector, lastsector, sectorsused, label, FileSystem::Fat32)
fat16(firstsector, lastsector, sectorsused, label, FileSystem::Type::Fat32)
{
}
qint64 fat32::minCapacity() const
{
return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 32 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 fat32::maxCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
bool fat32::create(Report& report, const QString& deviceNode)
@ -59,12 +59,7 @@ bool fat32::updateUUID(Report& report, const QString& deviceNode) const
// HACK: replace this hack with fatlabel "-i" (dosfstools 4.2)
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode, QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=67") });
if (!cmd.start())
return false;
if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid))
return false;
return cmd.waitFor(-1);
cmd.write(QByteArray(uuid, sizeof(uuid)));
return cmd.start();
}
}

View File

@ -1,7 +1,7 @@
/*************************************************************************
* Copyright (C) 2012 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2015 by Teo Mrnjavac <teo@kde.org> *
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
* Copyright (C) 2016-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -31,10 +31,12 @@
#include <KLocalizedString>
#include <QColor>
#include <QFileInfo>
#include <QStandardPaths>
#include <QStorageInfo>
const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode =
const std::vector<QColor> FileSystem::defaultColorCode =
{
{
QColor( 220,205,175 ), // unknown
@ -66,25 +68,40 @@ const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode
QColor( 170,120,255 ), // udf
QColor( 177,82,69 ), // iso9660
QColor( 223,39,104 ), // luks2
QColor( 204,179,255 ) // fat12
QColor( 204,179,255 ), // fat12
QColor( 255,100,100 ) // linux_raid_member
}
};
struct FileSystemPrivate {
FileSystem::Type m_Type;
qint64 m_FirstSector;
qint64 m_LastSector;
qint64 m_SectorSize;
qint64 m_SectorsUsed;
QString m_Label;
QString m_UUID;
};
/** Creates a new FileSystem object
@param firstsector the first sector used by this FileSystem on the Device
@param lastsector the last sector used by this FileSystem on the Device
@param sectorsused the number of sectors in use on the FileSystem
@param l the FileSystem label
@param t the FileSystem type
@param label the FileSystem label
@param type the FileSystem type
*/
FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& l, FileSystem::Type t) :
m_Type(t),
m_FirstSector(firstsector),
m_LastSector(lastsector),
m_SectorsUsed(sectorsused),
m_Label(l),
m_UUID()
FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type) :
d(std::make_unique<FileSystemPrivate>())
{
d->m_Type = type;
d->m_FirstSector = firstsector;
d->m_LastSector = lastsector;
d->m_SectorsUsed = sectorsused;
d->m_Label = label;
d->m_UUID = QString();
}
FileSystem::~FileSystem()
{
}
@ -106,7 +123,7 @@ FileSystem::Type FileSystem::detectFileSystem(const QString& partitionPath)
QString FileSystem::detectMountPoint(FileSystem* fs, const QString& partitionPath)
{
if (fs->type() == FileSystem::Lvm2_PV)
if (fs->type() == FileSystem::Type::Lvm2_PV)
return FS::lvm2_pv::getVGName(partitionPath);
if (partitionPath.isEmpty()) // Happens when during initial scan LUKS is closed
@ -131,7 +148,7 @@ bool FileSystem::detectMountStatus(FileSystem* fs, const QString& partitionPath)
{
bool mounted = false;
if (fs->type() == FileSystem::Lvm2_PV) {
if (fs->type() == FileSystem::Type::Lvm2_PV) {
mounted = FS::lvm2_pv::getVGName(partitionPath) != QString();
} else {
mounted = isMounted(partitionPath);
@ -360,13 +377,13 @@ bool FileSystem::updateBootSector(Report& report, const QString& deviceNode) con
/** @return the minimum capacity valid for this FileSystem in bytes */
qint64 FileSystem::minCapacity() const
{
return 8 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 8 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
/** @return the maximum capacity valid for this FileSystem in bytes */
qint64 FileSystem::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
/** @return the maximum label length valid for this FileSystem */
@ -390,6 +407,11 @@ QString FileSystem::name(const QStringList& languages) const
return nameForType(type(), languages);
}
FileSystem::Type FileSystem::type() const
{
return d->m_Type;
}
/** @return a pointer to a QString C array with all FileSystem names */
static const KLocalizedString* typeNames()
{
@ -424,7 +446,8 @@ static const KLocalizedString* typeNames()
kxi18nc("@item filesystem name", "udf"),
kxi18nc("@item filesystem name", "iso9660"),
kxi18nc("@item filesystem name", "luks2"),
kxi18nc("@item filesystem name", "fat12")
kxi18nc("@item filesystem name", "fat12"),
kxi18nc("@item filesystem name", "linux_raid_member"),
};
return s;
@ -435,10 +458,9 @@ static const KLocalizedString* typeNames()
*/
QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages)
{
Q_ASSERT(t >= 0);
Q_ASSERT(t < __lastType);
Q_ASSERT(t < Type::__lastType);
return typeNames()[t].toString(languages);
return typeNames()[static_cast<int>(t)].toString(languages);
}
/** @param s the name to get the type for
@ -446,11 +468,11 @@ QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages
*/
FileSystem::Type FileSystem::typeForName(const QString& s, const QStringList& languages )
{
for (quint32 i = 0; i < __lastType; i++)
for (quint32 i = 0; i < static_cast<int>(Type::__lastType); i++)
if (typeNames()[i].toString(languages) == s)
return static_cast<FileSystem::Type>(i);
return Unknown;
return Type::Unknown;
}
/** @return a QList of all known types */
@ -458,8 +480,8 @@ QList<FileSystem::Type> FileSystem::types()
{
QList<FileSystem::Type> result;
int i = Ext2; // first "real" filesystem
while (i != __lastType)
int i = static_cast<int>(Type::Ext2); // first "real" filesystem
while (i != static_cast<int>(Type::__lastType))
result.append(static_cast<FileSystem::Type>(i++));
return result;
@ -529,9 +551,25 @@ bool FileSystem::unmount(Report& report, const QString& deviceNode)
return false;
}
qint64 FileSystem::firstSector() const
{
return d->m_FirstSector;
}
qint64 FileSystem::lastSector() const
{
return d->m_LastSector;
}
bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode)
{
ExternalCommand cmd(cmdName, args);
QString cmdFullPath = QStandardPaths::findExecutable(cmdName);
if (cmdFullPath.isEmpty())
cmdFullPath = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") });
if (cmdFullPath.isEmpty())
return false;
ExternalCommand cmd(cmdFullPath, args);
if (!cmd.run())
return false;
@ -547,3 +585,53 @@ FileSystem::SupportTool FileSystem::supportToolName() const
{
return SupportTool();
}
void FileSystem::setFirstSector(qint64 s)
{
d->m_FirstSector = s;
}
void FileSystem::setLastSector(qint64 s)
{
d->m_LastSector = s;
}
const QString& FileSystem::label() const
{
return d->m_Label;
}
qint64 FileSystem::sectorSize() const
{
return d->m_SectorSize;
}
qint64 FileSystem::sectorsUsed() const
{
return d->m_SectorsUsed;
}
const QString& FileSystem::uuid() const
{
return d->m_UUID;
}
void FileSystem::setSectorSize(qint64 s)
{
d->m_SectorSize = s;
}
void FileSystem::setSectorsUsed(qint64 s)
{
d->m_SectorsUsed = s;
}
void FileSystem::setLabel(const QString& s)
{
d->m_Label = s;
}
void FileSystem::setUUID(const QString& s)
{
d->m_UUID = s;
}

View File

@ -1,7 +1,7 @@
/*************************************************************************
* Copyright (C) 2012 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2015 by Teo Mrnjavac <teo@kde.org> *
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
* Copyright (C) 2016-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -17,23 +17,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_FILESYSTEM_H)
#ifndef KPMCORE_FILESYSTEM_H
#define KPMCORE_FILESYSTEM_H
#include "util/libpartitionmanagerexport.h"
#include <QColor>
#include <QList>
#include <QStringList>
#include <QString>
#include <QtGlobal>
#include <QUrl>
#include <array>
#include <memory>
#include <vector>
class QColor;
class QValidator;
class Device;
class Report;
struct FileSystemPrivate;
/** Base class for all FileSystems.
@ -57,40 +59,41 @@ public:
};
/** Supported FileSystem types */
enum Type {
Unknown = 0,
Extended = 1,
enum Type : int {
Unknown,
Extended,
Ext2 = 2,
Ext3 = 3,
Ext4 = 4,
LinuxSwap = 5,
Fat16 = 6,
Fat32 = 7,
Ntfs = 8,
ReiserFS = 9,
Reiser4 = 10,
Xfs = 11,
Jfs = 12,
Hfs = 13,
HfsPlus = 14,
Ufs = 15,
Unformatted = 16,
Btrfs = 17,
Hpfs = 18,
Luks = 19,
Ocfs2 = 20,
Zfs = 21,
Exfat = 22,
Nilfs2 = 23,
Lvm2_PV = 24,
F2fs = 25,
Udf = 26,
Iso9660 = 27,
Luks2 = 28,
Fat12 = 29,
Ext2,
Ext3,
Ext4,
LinuxSwap,
Fat16,
Fat32,
Ntfs,
ReiserFS,
Reiser4,
Xfs,
Jfs,
Hfs,
HfsPlus,
Ufs,
Unformatted,
Btrfs,
Hpfs,
Luks,
Ocfs2,
Zfs,
Exfat,
Nilfs2,
Lvm2_PV,
F2fs,
Udf,
Iso9660,
Luks2,
Fat12,
LinuxRaidMember,
__lastType = 30
__lastType
};
/** The type of support for a given FileSystem action */
@ -101,15 +104,15 @@ public:
cmdSupportBackend = 4 /**< supported by the backend */
};
static const std::array< QColor, __lastType > defaultColorCode;
static const std::vector<QColor> defaultColorCode;
Q_DECLARE_FLAGS(CommandSupportTypes, CommandSupportType)
protected:
FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t);
FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type);
public:
virtual ~FileSystem() {}
virtual ~FileSystem();
public:
virtual void init() {}
@ -196,9 +199,11 @@ public:
* @see nameForType()
*/
virtual QString name(const QStringList& languages = {}) const;
virtual FileSystem::Type type() const {
return m_Type; /**< @return the FileSystem's type */
}
/**
* @return the FileSystem's type
*/
virtual FileSystem::Type type() const;
/**
* Returns the name of the given filesystem type. If @p languages
@ -228,12 +233,12 @@ public:
virtual bool mount(Report& report, const QString& deviceNode, const QString& mountPoint);
virtual bool unmount(Report& report, const QString& deviceNode);
qint64 firstSector() const {
return m_FirstSector; /**< @return the FileSystem's first sector */
}
qint64 lastSector() const {
return m_LastSector; /**< @return the FileSystem's last sector */
}
/**< @return the FileSystem's first sector */
qint64 firstSector() const;
/**< @return the FileSystem's last sector */
qint64 lastSector() const;
qint64 length() const {
return lastSector() - firstSector() + 1; /**< @return the FileSystem's length */
}
@ -244,52 +249,42 @@ public:
return firstByte() + length() * sectorSize() - 1; /**< @return the FileSystem's last byte */
}
void setFirstSector(qint64 s) {
m_FirstSector = s; /**< @param s the new first sector */
}
void setLastSector(qint64 s) {
m_LastSector = s; /**< @param s the new last sector */
}
/**< @param s the new first sector */
void setFirstSector(qint64 s);
/**< @param s the new last sector */
void setLastSector(qint64 s);
void move(qint64 newStartSector);
const QString& label() const {
return m_Label; /**< @return the FileSystem's label */
}
qint64 sectorSize() const {
return m_SectorSize; /**< @return the sector size in the underlying Device */
}
qint64 sectorsUsed() const {
return m_SectorsUsed; /**< @return the sectors in use on the FileSystem */
}
const QString& uuid() const {
return m_UUID; /**< @return the FileSystem's UUID */
}
/**< @return the FileSystem's label */
const QString& label() const;
void setSectorSize(qint64 s) {
m_SectorSize = s; /**< @param s the new value for sector size */
}
void setSectorsUsed(qint64 s) {
m_SectorsUsed = s; /**< @param s the new value for sectors in use */
}
void setLabel(const QString& s) {
m_Label = s; /**< @param s the new label */
}
void setUUID(const QString& s) {
m_UUID = s; /**< @param s the new UUID */
}
/**< @return the sector size in the underlying Device */
qint64 sectorSize() const;
/**< @return the sectors in use on the FileSystem */
qint64 sectorsUsed() const;
/**< @return the FileSystem's UUID */
const QString& uuid() const;
/**< @param s the new value for sector size */
void setSectorSize(qint64 s);
/**< @param s the new value for sectors in use */
void setSectorsUsed(qint64 s);
/**< @param s the new label */
void setLabel(const QString& s);
/**< @param s the new UUID */
void setUUID(const QString& s);
protected:
static bool findExternal(const QString& cmdName, const QStringList& args = QStringList(), int exptectedCode = 1);
protected:
FileSystem::Type m_Type;
qint64 m_FirstSector;
qint64 m_LastSector;
qint64 m_SectorSize;
qint64 m_SectorsUsed;
QString m_Label;
QString m_UUID;
std::unique_ptr<FileSystemPrivate> d;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(FileSystem::CommandSupportTypes)

36
src/fs/filesystem_p.h Normal file
View File

@ -0,0 +1,36 @@
/*************************************************************************
* Copyright (C) 2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#ifndef KPMCORE_FILESYSTEM_P_H
#define KPMCORE_FILESYSTEM_P_H
#include "fs/filesystem.h"
#include <QString>
class FileSystemPrivate {
public:
FileSystem::Type m_Type;
qint64 m_FirstSector;
qint64 m_LastSector;
qint64 m_SectorSize;
qint64 m_SectorsUsed;
QString m_Label;
QString m_UUID;
};
#endif

View File

@ -34,6 +34,7 @@
#include "fs/hpfs.h"
#include "fs/iso9660.h"
#include "fs/jfs.h"
#include "fs/linuxraidmember.h"
#include "fs/linuxswap.h"
#include "fs/luks.h"
#include "fs/luks2.h"
@ -61,36 +62,37 @@ void FileSystemFactory::init()
qDeleteAll(m_FileSystems);
m_FileSystems.clear();
m_FileSystems.insert(FileSystem::Btrfs, new FS::btrfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Exfat, new FS::exfat(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ext2, new FS::ext2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ext3, new FS::ext3(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ext4, new FS::ext4(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Extended, new FS::extended(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::F2fs, new FS::f2fs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Fat12, new FS::fat12(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Fat16, new FS::fat16(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Fat32, new FS::fat32(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Hfs, new FS::hfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::HfsPlus, new FS::hfsplus(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Hpfs, new FS::hpfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Iso9660, new FS::iso9660(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Jfs, new FS::jfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Luks, new FS::luks(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Luks2, new FS::luks2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Lvm2_PV, new FS::lvm2_pv(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Nilfs2, new FS::nilfs2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ntfs, new FS::ntfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ocfs2, new FS::ocfs2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::ReiserFS, new FS::reiserfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Reiser4, new FS::reiser4(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Udf, new FS::udf(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ufs, new FS::ufs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Unformatted, new FS::unformatted(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Unknown, new FS::unknown(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Xfs, new FS::xfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Zfs, new FS::zfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Btrfs, new FS::btrfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Exfat, new FS::exfat(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Ext2, new FS::ext2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Ext3, new FS::ext3(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Ext4, new FS::ext4(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Extended, new FS::extended(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::F2fs, new FS::f2fs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Fat12, new FS::fat12(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Fat16, new FS::fat16(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Fat32, new FS::fat32(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Hfs, new FS::hfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::HfsPlus, new FS::hfsplus(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Hpfs, new FS::hpfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Iso9660, new FS::iso9660(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Jfs, new FS::jfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::LinuxRaidMember, new FS::linuxraidmember(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Luks, new FS::luks(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Luks2, new FS::luks2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Lvm2_PV, new FS::lvm2_pv(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Nilfs2, new FS::nilfs2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Ntfs, new FS::ntfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Ocfs2, new FS::ocfs2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::ReiserFS, new FS::reiserfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Reiser4, new FS::reiser4(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Udf, new FS::udf(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Ufs, new FS::ufs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Unformatted, new FS::unformatted(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Unknown, new FS::unknown(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Xfs, new FS::xfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Type::Zfs, new FS::zfs(-1, -1, -1, QString()));
for (const auto &fs : FileSystemFactory::map())
fs->init();
@ -111,36 +113,37 @@ FileSystem* FileSystemFactory::create(FileSystem::Type t, qint64 firstsector, qi
FileSystem* fs = nullptr;
switch (t) {
case FileSystem::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break;
case FileSystem::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Zfs: fs = new FS::zfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::LinuxRaidMember: fs = new FS::linuxraidmember(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Type::Zfs: fs = new FS::zfs(firstsector, lastsector, sectorsused, label); break;
default: break;
}

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_FILESYSTEMFACTORY_H)
#ifndef KPMCORE_FILESYSTEMFACTORY_H
#define KPMCORE_FILESYSTEMFACTORY_H
#include "fs/filesystem.h"

View File

@ -35,7 +35,7 @@ FileSystem::CommandSupportType hfs::m_Copy = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType hfs::m_Backup = FileSystem::cmdSupportNone;
hfs::hfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Hfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Hfs)
{
}
@ -73,7 +73,7 @@ FileSystem::SupportTool hfs::supportToolName() const
qint64 hfs::maxCapacity() const
{
return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB);
return 2 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB);
}
int hfs::maxLabelLength() const

View File

@ -35,7 +35,7 @@ FileSystem::CommandSupportType hfsplus::m_Copy = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType hfsplus::m_Backup = FileSystem::cmdSupportNone;
hfsplus::hfsplus(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::HfsPlus)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::HfsPlus)
{
}
@ -73,7 +73,7 @@ FileSystem::SupportTool hfsplus::supportToolName() const
qint64 hfsplus::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
int hfsplus::maxLabelLength() const

View File

@ -37,12 +37,12 @@ FileSystem::CommandSupportType hpfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType hpfs::m_GetUUID = FileSystem::cmdSupportNone;
hpfs::hpfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Hpfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Hpfs)
{
}
qint64 hpfs::maxCapacity() const
{
return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB);
return 2 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB);
}
}

View File

@ -21,7 +21,7 @@ namespace FS
{
iso9660::iso9660(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Iso9660)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Iso9660)
{
}

View File

@ -40,7 +40,7 @@ FileSystem::CommandSupportType jfs::m_Backup = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType jfs::m_SetLabel = FileSystem::cmdSupportNone;
jfs::jfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Jfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Jfs)
{
}
@ -79,12 +79,12 @@ FileSystem::SupportTool jfs::supportToolName() const
qint64 jfs::minCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 jfs::maxCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB);
}
int jfs::maxLabelLength() const
@ -96,7 +96,7 @@ qint64 jfs::readUsedCapacity(const QString& deviceNode) const
{
ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode);
if (cmd.start() && cmd.write("dm") == 2 && cmd.waitFor()) {
if (cmd.write(QByteArrayLiteral("dm")) && cmd.start()) {
qint64 blockSize = -1;
QRegularExpression re(QStringLiteral("Block Size: (\\d+)"));
QRegularExpressionMatch reBlockSize = re.match(cmd.output());

View File

@ -0,0 +1,28 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "fs/linuxraidmember.h"
namespace FS
{
linuxraidmember::linuxraidmember(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::LinuxRaidMember)
{
}
}

41
src/fs/linuxraidmember.h Normal file
View File

@ -0,0 +1,41 @@
/*************************************************************************
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#ifndef LINUXRAIDMEMBER_H
#define LINUXRAIDMEMBER_H
#include "util/libpartitionmanagerexport.h"
#include "fs/filesystem.h"
class Report;
class QString;
namespace FS
{
/** A linux_raid_member file system.
@author Caio Carvalho <caiojcarvalho@gmail.com>
*/
class LIBKPMCORE_EXPORT linuxraidmember : public FileSystem
{
public:
linuxraidmember(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label);
};
}
#endif // LINUXRAIDMEMBER_H

View File

@ -40,7 +40,7 @@ FileSystem::CommandSupportType linuxswap::m_GetUUID = FileSystem::cmdSupportNone
FileSystem::CommandSupportType linuxswap::m_UpdateUUID = FileSystem::cmdSupportNone;
linuxswap::linuxswap(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::LinuxSwap)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::LinuxSwap)
{
}
@ -89,7 +89,7 @@ bool linuxswap::create(Report& report, const QString& deviceNode)
bool linuxswap::resize(Report& report, const QString& deviceNode, qint64 length) const
{
Q_UNUSED(length);
Q_UNUSED(length)
const QString label = readLabel(deviceNode);
const QString uuid = readUUID(deviceNode);
@ -145,14 +145,14 @@ QString linuxswap::unmountTitle() const
}
bool linuxswap::canMount(const QString& deviceNode, const QString& mountPoint) const {
Q_UNUSED(deviceNode);
Q_UNUSED(deviceNode)
// linux swap doesn't require mount point to activate
return mountPoint != QStringLiteral("/");
}
bool linuxswap::mount(Report& report, const QString& deviceNode, const QString& mountPoint)
{
Q_UNUSED(mountPoint);
Q_UNUSED(mountPoint)
ExternalCommand cmd(report, QStringLiteral("swapon"), { deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0;
}

View File

@ -39,6 +39,7 @@
#include <QStorageInfo>
#include <QString>
#include <QUuid>
#include <QWidget>
#include <KLocalizedString>
#include <KPasswordDialog>
@ -129,9 +130,8 @@ bool luks::create(Report& report, const QString& deviceNode)
QStringLiteral("--type"), QStringLiteral("luks1"),
QStringLiteral("luksFormat"),
deviceNode });
if (!( createCmd.start(-1) &&
createCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 &&
createCmd.waitFor() && createCmd.exitCode() == 0))
if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') &&
createCmd.start(-1) && createCmd.exitCode() == 0))
{
return false;
}
@ -141,7 +141,7 @@ bool luks::create(Report& report, const QString& deviceNode)
deviceNode,
suggestedMapperName(deviceNode) });
if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor()))
if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1)))
return false;
setPayloadSize();
@ -168,12 +168,12 @@ QString luks::unmountTitle() const
QString luks::cryptOpenTitle() const
{
return xi18nc("@title:menu", "Decrypt");
return xi18nc("@title:menu", "Unlock");
}
QString luks::cryptCloseTitle() const
{
return xi18nc("@title:menu", "Deactivate");
return xi18nc("@title:menu", "Lock");
}
void luks::setPassphrase(const QString& passphrase)
@ -265,9 +265,8 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
deviceNode,
suggestedMapperName(deviceNode) });
if (!( openCmd.start(-1) &&
openCmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 &&
openCmd.waitFor() && openCmd.exitCode() == 0) )
if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') &&
openCmd.start(-1) && openCmd.exitCode() == 0) )
return false;
if (m_innerFs) {
@ -286,8 +285,8 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
if (!m_isCryptOpen)
return false;
for (auto &p : LVM::pvList)
if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Lvm2_PV)
for (auto &p : LVM::pvList::list())
if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Type::Lvm2_PV)
p.setLuks(false);
m_passphrase = passphrase;
@ -325,7 +324,7 @@ bool luks::cryptClose(const QString& deviceNode)
m_isCryptOpen = (m_innerFs != nullptr);
for (auto &p : LVM::pvList)
for (auto &p : LVM::pvList::list())
if (!p.isLuks() && p.partition()->deviceNode() == deviceNode)
p.setLuks(true);
@ -464,7 +463,7 @@ FileSystem::Type luks::type() const
{
if (m_isCryptOpen && m_innerFs)
return m_innerFs->type();
return FileSystem::Luks;
return FileSystem::Type::Luks;
}
QString luks::suggestedMapperName(const QString& deviceNode) const
@ -647,19 +646,19 @@ bool luks::canEncryptType(FileSystem::Type type)
{
switch (type)
{
case Btrfs:
case F2fs:
case Ext2:
case Ext3:
case Ext4:
case Jfs:
case LinuxSwap:
case Lvm2_PV:
case Nilfs2:
case ReiserFS:
case Reiser4:
case Xfs:
case Zfs:
case Type::Btrfs:
case Type::F2fs:
case Type::Ext2:
case Type::Ext3:
case Type::Ext4:
case Type::Jfs:
case Type::LinuxSwap:
case Type::Lvm2_PV:
case Type::Nilfs2:
case Type::ReiserFS:
case Type::Reiser4:
case Type::Xfs:
case Type::Zfs:
return true;
default:
return false;
@ -690,7 +689,7 @@ void luks::setPayloadSize()
bool luks::testPassphrase(const QString& deviceNode, const QString& passphrase) const {
ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), QStringLiteral("--test-passphrase"), deviceNode });
if (cmd.start(-1) && cmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 && cmd.waitFor() && cmd.exitCode() == 0)
if (cmd.write(passphrase.toLocal8Bit() + '\n') && cmd.start(-1) && cmd.exitCode() == 0)
return true;
return false;

View File

@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#if !defined(KPMCORE_LUKS_H)
#ifndef KPMCORE_LUKS_H
#define KPMCORE_LUKS_H
#include "util/libpartitionmanagerexport.h"
@ -26,11 +25,11 @@
#include "fs/filesystem.h"
#include <QtGlobal>
#include <QWidget>
class Report;
class QString;
class QWidget;
namespace FS
{
@ -40,10 +39,10 @@ namespace FS
class LIBKPMCORE_EXPORT luks : public FileSystem
{
public:
luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Luks);
luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Luks);
~luks() override;
enum KeyLocation {
enum class KeyLocation {
unknown,
dmcrypt,
keyring
@ -225,7 +224,7 @@ protected:
qint64 m_PayloadSize;
QString m_outerUuid;
luks::KeyLocation m_KeyLocation = unknown;
luks::KeyLocation m_KeyLocation = KeyLocation::unknown;
};
}

View File

@ -28,7 +28,7 @@ namespace FS
{
luks2::luks2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label)
: luks(firstsector, lastsector, sectorsused, label, FileSystem::Luks2)
: luks(firstsector, lastsector, sectorsused, label, FileSystem::Type::Luks2)
{
}
@ -40,7 +40,7 @@ FileSystem::Type luks2::type() const
{
if (m_isCryptOpen && m_innerFs)
return m_innerFs->type();
return FileSystem::Luks2;
return FileSystem::Type::Luks2;
}
bool luks2::create(Report& report, const QString& deviceNode)
@ -56,9 +56,8 @@ bool luks2::create(Report& report, const QString& deviceNode)
QStringLiteral("--type"), QStringLiteral("luks2"),
QStringLiteral("luksFormat"),
deviceNode });
if (!( createCmd.start(-1) &&
createCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 &&
createCmd.waitFor() && createCmd.exitCode() == 0))
if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') &&
createCmd.start(-1) && createCmd.exitCode() == 0))
{
return false;
}
@ -68,7 +67,7 @@ bool luks2::create(Report& report, const QString& deviceNode)
deviceNode,
suggestedMapperName(deviceNode) });
if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor()))
if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1)))
return false;
setPayloadSize();
@ -95,13 +94,13 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength)
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
cryptResizeCmd.start(-1);
if (m_KeyLocation == keyring) {
if (m_KeyLocation == KeyLocation::keyring) {
if (m_passphrase.isEmpty())
return false;
cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
}
cryptResizeCmd.waitFor();
if (!cryptResizeCmd.start(-1))
return false;
if ( cryptResizeCmd.exitCode() == 0 )
return m_innerFs->resize(report, mapperName(), m_PayloadSize);
}
@ -111,13 +110,13 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength)
{ QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // FIXME, LUKS2 can have different sector sizes
QStringLiteral("resize"), mapperName() });
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
cryptResizeCmd.start(-1);
if (m_KeyLocation == keyring) {
if (m_KeyLocation == KeyLocation::keyring) {
if (m_passphrase.isEmpty())
return false;
cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
}
cryptResizeCmd.waitFor();
if (!cryptResizeCmd.start(-1))
return false;
if ( cryptResizeCmd.exitCode() == 0 )
return true;
}
@ -127,16 +126,16 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength)
luks::KeyLocation luks2::keyLocation()
{
m_KeyLocation = unknown;
m_KeyLocation = KeyLocation::unknown;
ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() });
if (statusCmd.run(-1) && statusCmd.exitCode() == 0) {
QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)"));
QRegularExpressionMatch rem = re.match(statusCmd.output());
if (rem.hasMatch()) {
if (rem.captured(1) == QStringLiteral("keyring"))
m_KeyLocation = keyring;
m_KeyLocation = KeyLocation::keyring;
else if (rem.captured(1) == QStringLiteral("dm-crypt"))
m_KeyLocation = dmcrypt;
m_KeyLocation = KeyLocation::dmcrypt;
}
}

View File

@ -43,7 +43,7 @@ FileSystem::CommandSupportType lvm2_pv::m_GetUUID = FileSystem::cmdSupportNone;
lvm2_pv::lvm2_pv(qint64 firstsector, qint64 lastsector,
qint64 sectorsused, const QString& label)
: FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Lvm2_PV)
: FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Lvm2_PV)
, m_PESize(0)
, m_TotalPE(0)
, m_AllocatedPE(0)
@ -99,7 +99,7 @@ FileSystem::SupportTool lvm2_pv::supportToolName() const
qint64 lvm2_pv::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
qint64 lvm2_pv::readUsedCapacity(const QString& deviceNode) const
@ -270,10 +270,10 @@ QList<LvmPV> lvm2_pv::getPVinNode(const PartitionNode* parent)
partitions.append(getPVinNode(node));
// FIXME: reenable newly created PVs (before applying) once everything works
if(p->fileSystem().type() == FileSystem::Lvm2_PV && p->deviceNode() == p->partitionPath())
if(p->fileSystem().type() == FileSystem::Type::Lvm2_PV && p->deviceNode() == p->partitionPath())
partitions.append(LvmPV(p->mountPoint(), p));
if(p->fileSystem().type() == FileSystem::Luks && p->deviceNode() == p->partitionPath())
if(p->fileSystem().type() == FileSystem::Type::Luks && p->deviceNode() == p->partitionPath())
partitions.append(LvmPV(p->mountPoint(), p, true));
}
@ -296,7 +296,11 @@ QList<LvmPV> lvm2_pv::getPVs(const QList<Device*>& devices)
}
QList<LvmPV> LVM::pvList;
namespace LVM {
QList<LvmPV> pvList::m_list;
}
LvmPV::LvmPV(const QString vgName, const Partition* p, bool isLuks)
: m_vgName(vgName)

View File

@ -62,7 +62,22 @@ private:
};
namespace LVM {
extern LIBKPMCORE_EXPORT QList<LvmPV> pvList;
/** Class to access a global LVM PV list.
@author Caio Carvalho <caiojcarvalho@gmail.com>
*/
class LIBKPMCORE_EXPORT pvList
{
public:
static QList<LvmPV> &list() {
return m_list;
}
private:
pvList() { }
private:
static QList<LvmPV> m_list;
};
}
namespace FS

View File

@ -47,7 +47,7 @@ FileSystem::CommandSupportType nilfs2::m_UpdateUUID = FileSystem::cmdSupportNone
FileSystem::CommandSupportType nilfs2::m_GetUUID = FileSystem::cmdSupportNone;
nilfs2::nilfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Nilfs2)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Nilfs2)
{
}
@ -96,12 +96,12 @@ FileSystem::SupportTool nilfs2::supportToolName() const
qint64 nilfs2::minCapacity() const
{
return 128 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 128 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 nilfs2::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
int nilfs2::maxLabelLength() const

View File

@ -50,7 +50,7 @@ FileSystem::CommandSupportType ntfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType ntfs::m_GetUUID = FileSystem::cmdSupportNone;
ntfs::ntfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Ntfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ntfs)
{
}
@ -91,12 +91,12 @@ FileSystem::SupportTool ntfs::supportToolName() const
qint64 ntfs::minCapacity() const
{
return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 2 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 ntfs::maxCapacity() const
{
return 256 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB);
return 256 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB);
}
int ntfs::maxLabelLength() const
@ -125,8 +125,7 @@ qint64 ntfs::readUsedCapacity(const QString& deviceNode) const
bool ntfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel)
{
ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel });
writeCmd.setProcessChannelMode(QProcess::SeparateChannels);
ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }, QProcess::SeparateChannels);
if (!writeCmd.run(-1))
return false;
@ -171,7 +170,7 @@ bool ntfs::resize(Report& report, const QString& deviceNode, qint64 length) cons
bool ntfs::updateUUID(Report& report, const QString& deviceNode) const
{
Q_UNUSED(report);
Q_UNUSED(report)
ExternalCommand cmd(QStringLiteral("ntfslabel"), { QStringLiteral("--new-serial"), deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0;
@ -191,24 +190,22 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=28") });
cmd.write(QByteArray(s, sizeof(s)));
if (!cmd.start()) {
Log() << xi18nc("@info:progress", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode);
return false;
}
cmd.write(QByteArray(s, sizeof(s)));
cmd.waitFor(-1);
// Also update backup NTFS boot sector located at the end of the partition
// NOTE: this should fail if filesystem does not span the whole partition
qint64 pos = (lastSector() - firstSector()) * sectorSize() + 28;
ExternalCommand cmd2(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=") + QString::number(pos) });
cmd2.write(QByteArray(s, sizeof(s)));
if (!cmd2.start()) {
Log() << xi18nc("@info:progress", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode);
return false;
}
cmd2.write(QByteArray(s, sizeof(s)));
cmd2.waitFor(-1);
Log() << xi18nc("@info:progress", "Updated NTFS boot sector for partition <filename>%1</filename> successfully.", deviceNode);

View File

@ -40,7 +40,7 @@ FileSystem::CommandSupportType ocfs2::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType ocfs2::m_GetUUID = FileSystem::cmdSupportNone;
ocfs2::ocfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Ocfs2)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ocfs2)
{
}
@ -89,17 +89,17 @@ FileSystem::SupportTool ocfs2::supportToolName() const
qint64 ocfs2::minCapacity() const
{
return 14000 * Capacity::unitFactor(Capacity::Byte, Capacity::KiB);
return 14000 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::KiB);
}
qint64 ocfs2::maxCapacity() const
{
return 4 * Capacity::unitFactor(Capacity::Byte, Capacity::PiB);
return 4 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::PiB);
}
qint64 ocfs2::readUsedCapacity(const QString& deviceNode) const
{
Q_UNUSED(deviceNode);
Q_UNUSED(deviceNode)
return -1;
}
@ -113,15 +113,12 @@ bool ocfs2::create(Report& report, const QString& deviceNode)
{
ExternalCommand cmd(report, QStringLiteral("mkfs.ocfs2"), { deviceNode });
if (cmd.start())
{
cmd.write("y\n");
cmd.waitFor(-1);
return cmd.exitCode() == 0;
}
else
cmd.write("y\n");
if (!cmd.start())
return false;
return cmd.exitCode() == 0;
}
bool ocfs2::resize(Report& report, const QString& deviceNode, qint64 length) const

View File

@ -35,7 +35,7 @@ FileSystem::CommandSupportType reiser4::m_Copy = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType reiser4::m_Backup = FileSystem::cmdSupportNone;
reiser4::reiser4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Reiser4)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Reiser4)
{
}
@ -75,7 +75,7 @@ qint64 reiser4::maxCapacity() const
{
// looks like it's actually unknown. see
// http://en.wikipedia.org/wiki/Comparison_of_file_systems
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
int reiser4::maxLabelLength() const

View File

@ -42,7 +42,7 @@ FileSystem::CommandSupportType reiserfs::m_UpdateUUID = FileSystem::cmdSupportNo
FileSystem::CommandSupportType reiserfs::m_GetUUID = FileSystem::cmdSupportNone;
reiserfs::reiserfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::ReiserFS)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::ReiserFS)
{
}
@ -85,12 +85,12 @@ FileSystem::SupportTool reiserfs::supportToolName() const
qint64 reiserfs::minCapacity() const
{
return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 32 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 reiserfs::maxCapacity() const
{
return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
int reiserfs::maxLabelLength() const
@ -154,15 +154,15 @@ bool reiserfs::resize(Report& report, const QString& deviceNode, qint64 length)
ExternalCommand cmd(report, QStringLiteral("resize_reiserfs"),
{ deviceNode, QStringLiteral("-q"), QStringLiteral("-s"), QString::number(length) });
bool rval = cmd.start(-1);
bool rval = cmd.write(QByteArrayLiteral("y\n"));
if (!rval)
return false;
if (cmd.write("y\n", 2) != 2)
if (!cmd.start(-1))
return false;
return cmd.waitFor(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 256);
return cmd.exitCode() == 0 || cmd.exitCode() == 256;
}
bool reiserfs::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const

View File

@ -40,7 +40,7 @@ FileSystem::CommandSupportType udf::m_Create = FileSystem::cmdSupportNone;
bool udf::oldMkudffsVersion = false;
udf::udf(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Udf)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Udf)
{
}

View File

@ -24,7 +24,7 @@ FileSystem::CommandSupportType ufs::m_Copy = FileSystem::cmdSupportCore;
FileSystem::CommandSupportType ufs::m_Backup = FileSystem::cmdSupportCore;
ufs::ufs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Ufs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ufs)
{
}
}

View File

@ -22,7 +22,7 @@ namespace FS
FileSystem::CommandSupportType unformatted::m_Create = FileSystem::cmdSupportFileSystem;
unformatted::unformatted(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Unformatted)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Unformatted)
{
}

View File

@ -20,7 +20,7 @@
namespace FS
{
unknown::unknown(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Unknown)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Unknown)
{
}

View File

@ -42,7 +42,7 @@ FileSystem::CommandSupportType xfs::m_Backup = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType xfs::m_SetLabel = FileSystem::cmdSupportNone;
xfs::xfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Xfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Xfs)
{
}
@ -83,12 +83,12 @@ FileSystem::SupportTool xfs::supportToolName() const
qint64 xfs::minCapacity() const
{
return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 32 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 xfs::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
int xfs::maxLabelLength() const

View File

@ -40,7 +40,7 @@ FileSystem::CommandSupportType zfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType zfs::m_GetUUID = FileSystem::cmdSupportNone;
zfs::zfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) :
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Zfs)
FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Zfs)
{
}
@ -77,12 +77,12 @@ FileSystem::SupportTool zfs::supportToolName() const
qint64 zfs::minCapacity() const
{
return 64 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB);
return 64 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
}
qint64 zfs::maxCapacity() const
{
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB);
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
bool zfs::remove(Report& report, const QString& deviceNode) const

View File

@ -21,10 +21,10 @@
#include "fs/filesystem.h"
#include "util/capacity.h"
#include <QPainter>
#include <QStyleOptionButton>
#include <QApplication>
#include <QFontDatabase>
#include <QPainter>
#include <QStyleOptionButton>
/** Creates a new PartWidget
@param parent pointer to the parent widget
@ -71,7 +71,7 @@ void PartWidget::updateChildren()
}
}
void PartWidget::setFileSystemColorCode(const std::array< QColor, FileSystem::__lastType >& colorCode)
void PartWidget::setFileSystemColorCode(const std::vector<QColor>& colorCode)
{
m_fileSystemColorCode = colorCode;
repaint();
@ -101,12 +101,12 @@ void PartWidget::paintEvent(QPaintEvent*)
if (partition()->roles().has(PartitionRole::Extended)) {
drawGradient(&painter, activeColor(
m_fileSystemColorCode[ partition()->fileSystem().type() ]),
m_fileSystemColorCode[ static_cast<int>(partition()->fileSystem().type()) ]),
QRect(0, 0, width(), height()));
return;
}
const QColor base = activeColor(m_fileSystemColorCode[ partition()->fileSystem().type() ]);
const QColor base = activeColor(m_fileSystemColorCode[ static_cast<int>(partition()->fileSystem().type()) ]);
if (!partition()->roles().has(PartitionRole::Unallocated)) {
const QColor dark = base.darker(105);

View File

@ -26,8 +26,6 @@
#include <QColor>
#include <array>
class Partition;
class QPaintEvent;
@ -63,7 +61,7 @@ public:
return m_Partition; /**< @return the widget's Partition */
}
void setFileSystemColorCode( const std::array< QColor, FileSystem::__lastType >& colorCode );
void setFileSystemColorCode( const std::vector<QColor>& colorCode );
protected:
void paintEvent(QPaintEvent* event);
@ -76,7 +74,7 @@ protected:
private:
Partition* m_Partition;
bool m_Active;
std::array< QColor, FileSystem::__lastType > m_fileSystemColorCode;
std::vector<QColor> m_fileSystemColorCode;
};
#endif

View File

@ -24,7 +24,7 @@
#include "core/copytargetfile.h"
#include "fs/filesystem.h"
#include "util/externalcommand.h"
#include "util/report.h"
#include <KLocalizedString>

Some files were not shown because too many files have changed in this diff Show More