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) 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_USE_RELATIVE_PATHS OFF)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) 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_MAJOR "3")
set(VERSION_MINOR "3") set(VERSION_MINOR "50")
set(VERSION_RELEASE "0") set(VERSION_RELEASE "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE})
set(SOVERSION "8") set(SOVERSION "8")
@ -32,7 +40,7 @@ add_definitions(-D'VERSION="${VERSION}"') #"
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON) 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/") set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
include(KDEInstallDirs) include(KDEInstallDirs)
@ -41,7 +49,6 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
include(FeatureSummary) include(FeatureSummary)
include(GenerateExportHeader) include(GenerateExportHeader)
include(ECMSetupVersion) include(ECMSetupVersion)
include(ECMPackageConfigHelpers)
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h" 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 # Load the frameworks we need
find_package(KF5 REQUIRED find_package(KF5 ${KF5_MIN_VERSION} REQUIRED
Auth
I18n I18n
CoreAddons CoreAddons
WidgetsAddons WidgetsAddons
) )
find_package(Qca-qt5 REQUIRED)
# use sane compile flags # use sane compile flags
add_definitions( add_definitions(
-DQT_USE_QSTRINGBUILDER -DQT_USE_QSTRINGBUILDER
@ -76,10 +86,10 @@ add_definitions(
) )
kde_enable_exceptions() kde_enable_exceptions()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(BLKID REQUIRED blkid>=2.30) pkg_check_modules(BLKID REQUIRED blkid>=${BLKID_MIN_VERSION})
pkg_check_modules(LIBATASMART REQUIRED libatasmart) endif()
include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/) 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(INCLUDE_INSTALL_DIR "include/kpmcore/")
set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/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" "${CMAKE_CURRENT_BINARY_DIR}/KPMcoreConfig.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
PATH_VARS INCLUDE_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 1. Dependencies
libparted: Either get it from http://www.gnu.org/software/parted/download.shtml util-linux 2.32: available at https://github.com/karelzak/util-linux
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
KDE Frameworks: The minimum required version is 5.0. KDE Frameworks: The minimum required version is 5.0.
2. Configure 2. Configure
KPMcore is built with cmake. It is recommended to build out of tree: 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: 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 $ cd kpmcore-x.y.z
$ mkdir build $ mkdir build
$ cd 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 There are multiple backends so that KPMcore can support different
operating systems, although the only functional backend is the operating systems, although the only functional backend is the
one for Linux systems: one for Linux systems:
* libparted backend (Linux) * sfdisk backend (Linux)
* null backend * null backend
## Using KPMcore ## 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}) ki18n_wrap_ui(kpmcore_SRCS ${gui_UIFILES})
add_library(kpmcore SHARED ${kpmcore_SRCS}) add_library(kpmcore SHARED ${kpmcore_SRCS})
target_link_libraries( kpmcore target_link_libraries( kpmcore PUBLIC
${UUID_LIBRARIES} Qt5::Core
PRIVATE
${BLKID_LIBRARIES} ${BLKID_LIBRARIES}
${LIBATASMART_LIBRARIES}
Qt5::DBus Qt5::DBus
Qt5::Gui
qca-qt5
KF5::I18n KF5::I18n
KF5::CoreAddons KF5::CoreAddons
KF5::WidgetsAddons KF5::WidgetsAddons
KF5::Auth
) )
install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS})

View File

@ -24,20 +24,18 @@
#include <QDebug> #include <QDebug>
class CoreBackend::CoreBackendPrivate struct CoreBackendPrivate
{ {
public: QString m_id, m_version;
CoreBackendPrivate() {}
}; };
CoreBackend::CoreBackend() : CoreBackend::CoreBackend() :
d(new CoreBackendPrivate()) d(std::make_unique<CoreBackendPrivate>())
{ {
} }
CoreBackend::~CoreBackend() CoreBackend::~CoreBackend()
{ {
delete d;
} }
void CoreBackend::emitProgress(int i) void CoreBackend::emitProgress(int i)
@ -59,3 +57,23 @@ void CoreBackend::setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_pr
{ {
p.setMaxPrimaries(max_primaries); 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 "util/libpartitionmanagerexport.h"
#include "fs/filesystem.h" #include "fs/filesystem.h"
#include <memory>
#include <QObject> #include <QObject>
#include <QList> #include <QList>
class CoreBackendManager; class CoreBackendManager;
class CoreBackendDevice; class CoreBackendDevice;
struct CoreBackendPrivate;
class Device; class Device;
class PartitionTable; 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
* @return the plugin's unique Id from JSON metadata * @return the plugin's unique Id from JSON metadata
*/ */
QString id() { QString id();
return m_id;
}
/** /**
* Return the plugin's version from JSON metadata * Return the plugin's version from JSON metadata
* @return the plugin's version from JSON metadata * @return the plugin's version from JSON metadata
*/ */
QString version() { QString version();
return m_version;
}
/** /**
* Initialize the plugin's FileSystem support * Initialize the plugin's FileSystem support
@ -130,29 +129,23 @@ public:
/** /**
* Open a device for reading. * Open a device for reading.
* @param deviceNode The path of the device that is to be opened (e.g. /dev/sda) * @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 * @return a pointer to a CoreBackendDevice or nullptr if the open failed.
* an instance is returned, it's the caller's responsibility to delete the
* object.
*/ */
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. * Open a device in exclusive mode for writing.
* @param deviceNode The path of the device that is to be opened (e.g. /dev/sda) * @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 * @return a pointer to a CoreBackendDevice or nullptr if the open failed.
* an instance is returned, it's the caller's responsibility to delete the
* object.
*/ */
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. * Close a CoreBackendDevice that has previously been opened.
* @param core_device Pointer to the CoreBackendDevice to be closed. Must not be nullptr. * @param core_device Pointer to the CoreBackendDevice to be closed. Must not be nullptr.
* @return true if closing the CoreBackendDevice succeeded, otherwise false. * @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. * Emit progress.
@ -176,18 +169,11 @@ protected:
static void setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_primaries); static void setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_primaries);
private: private:
void setId(const QString& id) { void setId(const QString& id);
m_id = id; void setVersion(const QString& version);
}
void setVersion(const QString& version) {
m_version = version;
}
private: private:
QString m_id, m_version; std::unique_ptr<CoreBackendPrivate> d;
class CoreBackendPrivate;
CoreBackendPrivate* d;
}; };
#endif #endif

View File

@ -19,6 +19,7 @@
#define KPMCORE_COREBACKENDDEVICE_H #define KPMCORE_COREBACKENDDEVICE_H
#include <memory>
#include <QString> #include <QString>
class CoreBackendPartition; class CoreBackendPartition;
@ -81,7 +82,7 @@ public:
* @return a pointer to the CoreBackendPartitionTable for this device or nullptr in case * @return a pointer to the CoreBackendPartitionTable for this device or nullptr in case
* of errors * of errors
*/ */
virtual CoreBackendPartitionTable* openPartitionTable() = 0; virtual std::unique_ptr<CoreBackendPartitionTable> openPartitionTable() = 0;
/** /**
* Create a new partition table on this device. * Create a new partition table on this device.
@ -91,23 +92,6 @@ public:
*/ */
virtual bool createPartitionTable(Report& report, const PartitionTable& ptable) = 0; 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: protected:
void setExclusive(bool b) { void setExclusive(bool b) {
m_Exclusive = b; m_Exclusive = b;

View File

@ -1,7 +1,7 @@
/************************************************************************* /*************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> * * Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2015 by Teo Mrnjavac <teo@kde.org> * * 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -20,8 +20,8 @@
#include "backend/corebackendmanager.h" #include "backend/corebackendmanager.h"
#include "backend/corebackend.h" #include "backend/corebackend.h"
#include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QStringList>
#include <QString> #include <QString>
#include <QVector> #include <QVector>
@ -30,8 +30,17 @@
#include <KPluginLoader> #include <KPluginLoader>
#include <KPluginMetaData> #include <KPluginMetaData>
struct CoreBackendManagerPrivate
{
CoreBackend *m_Backend;
};
CoreBackendManager::CoreBackendManager() : CoreBackendManager::CoreBackendManager() :
m_Backend(nullptr) d(std::make_unique<CoreBackendManagerPrivate>())
{
}
CoreBackendManager::~CoreBackendManager()
{ {
} }
@ -45,6 +54,11 @@ CoreBackendManager* CoreBackendManager::self()
return instance; return instance;
} }
CoreBackend* CoreBackendManager::backend()
{
return d->m_Backend;
}
QVector<KPluginMetaData> CoreBackendManager::list() const QVector<KPluginMetaData> CoreBackendManager::list() const
{ {
auto filter = [&](const KPluginMetaData &metaData) { auto filter = [&](const KPluginMetaData &metaData) {
@ -66,7 +80,7 @@ bool CoreBackendManager::load(const QString& name)
KPluginFactory* factory = loader.factory(); KPluginFactory* factory = loader.factory();
if (factory != nullptr) { if (factory != nullptr) {
m_Backend = factory->create<CoreBackend>(nullptr); d->m_Backend = factory->create<CoreBackend>(nullptr);
QString id = loader.metaData().toVariantMap().value(QStringLiteral("MetaData")) QString id = loader.metaData().toVariantMap().value(QStringLiteral("MetaData"))
.toMap().value(QStringLiteral("KPlugin")).toMap().value(QStringLiteral("Id")).toString(); .toMap().value(QStringLiteral("KPlugin")).toMap().value(QStringLiteral("Id")).toString();
@ -78,6 +92,7 @@ bool CoreBackendManager::load(const QString& name)
backend()->setId(id); backend()->setId(id);
backend()->setVersion(version); backend()->setVersion(version);
qDebug() << "Loaded backend plugin: " << backend()->id(); qDebug() << "Loaded backend plugin: " << backend()->id();
return true; return true;
} }
@ -87,6 +102,4 @@ bool CoreBackendManager::load(const QString& name)
void CoreBackendManager::unload() 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) 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * 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/>.* * 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 #define KPMCORE_COREBACKENDMANAGER_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
#include <memory>
#include <QVector> #include <QVector>
class QString; class QString;
class QStringList; class QStringList;
class KPluginMetaData; class KPluginMetaData;
class CoreBackend; class CoreBackend;
struct CoreBackendManagerPrivate;
/** /**
* The backend manager class. * The backend manager class.
@ -37,8 +40,8 @@ class CoreBackend;
*/ */
class LIBKPMCORE_EXPORT CoreBackendManager class LIBKPMCORE_EXPORT CoreBackendManager
{ {
private:
CoreBackendManager(); CoreBackendManager();
~CoreBackendManager();
public: public:
/** /**
@ -50,7 +53,7 @@ public:
* @return the name of the default backend plugin * @return the name of the default backend plugin
*/ */
static QString defaultBackendName() { static QString defaultBackendName() {
return QStringLiteral("pmlibpartedbackendplugin"); return QStringLiteral("pmsfdiskbackendplugin");
} }
/** /**
@ -73,12 +76,10 @@ public:
/** /**
* @return a pointer to the currently loaded backend * @return a pointer to the currently loaded backend
*/ */
CoreBackend* backend() { CoreBackend* backend();
return m_Backend;
}
private: private:
CoreBackend* m_Backend; std::unique_ptr<CoreBackendManagerPrivate> d;
}; };
#endif #endif

View File

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

View File

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

View File

@ -20,7 +20,6 @@
#include "backend/corebackend.h" #include "backend/corebackend.h"
#include "backend/corebackendmanager.h" #include "backend/corebackendmanager.h"
#include "backend/corebackenddevice.h"
#include "core/copytarget.h" #include "core/copytarget.h"
#include "core/copytargetdevice.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 /** Opens the Device
@return true if the Device could be successfully opened @return true if the Device could be successfully opened
*/ */
@ -63,22 +56,6 @@ qint64 CopySourceDevice::length() const
return lastByte() - firstByte() + 1; 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 /** Checks if this CopySourceDevice overlaps with the given CopyTarget
@param target the CopyTarget to check overlapping with @param target the CopyTarget to check overlapping with
@return true if overlaps @return true if overlaps
@ -103,3 +80,8 @@ bool CopySourceDevice::overlaps(const CopyTarget& target) const
return false; return false;
} }
QString CopySourceDevice::path() const
{
return m_Device.deviceNode();
}

View File

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

View File

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

View File

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

View File

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

View File

@ -19,11 +19,9 @@
#include "backend/corebackend.h" #include "backend/corebackend.h"
#include "backend/corebackendmanager.h" #include "backend/corebackendmanager.h"
#include "backend/corebackenddevice.h"
#include "core/device.h" #include "core/device.h"
/** Constructs a device to copy to. /** Constructs a device to copy to.
@param d the Device to copy to @param d the Device to copy to
@param firstbyte the first byte on the Device to write 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. /** Opens a CopyTargetDevice for writing to.
@return true on success @return true on success
*/ */
@ -53,21 +45,7 @@ bool CopyTargetDevice::open()
return m_BackendDevice != nullptr; return m_BackendDevice != nullptr;
} }
/** Writes the given number of bytes to the Device. QString CopyTargetDevice::path() const
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)
{ {
Q_ASSERT(writeOffset >= 0); return m_Device.deviceNode();
bool rval = m_BackendDevice->writeData(buffer, writeOffset);
if (rval)
setBytesWritten(bytesWritten() + buffer.size());
return rval;
} }

View File

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

View File

@ -33,21 +33,3 @@ bool CopyTargetFile::open()
{ {
return file().open(QIODevice::WriteOnly | QIODevice::Truncate); 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: public:
bool open() override; bool open() override;
bool writeData(QByteArray& buffer, qint64 writeOffset) override;
qint64 firstByte() const override { qint64 firstByte() const override {
return 0; /**< @return always 0 for a file */ return 0; /**< @return always 0 for a file */
@ -49,6 +48,10 @@ public:
return bytesWritten(); /**< @return the number of bytes written so far */ return bytesWritten(); /**< @return the number of bytes written so far */
} }
QString path() const override {
return m_File.fileName();
}
protected: protected:
QFile& file() { QFile& file() {
return m_File; return m_File;

View File

@ -1,6 +1,6 @@
/************************************************************************* /*************************************************************************
* Copyright (C) 2008 by Volker Lanz <vl@fidra.de> * * 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -17,6 +17,7 @@
*************************************************************************/ *************************************************************************/
#include "core/device.h" #include "core/device.h"
#include "core/device_p.h"
#include "core/partitiontable.h" #include "core/partitiontable.h"
#include "core/smartstatus.h" #include "core/smartstatus.h"
@ -28,22 +29,24 @@
@param name the Device's name, usually some string defined by the manufacturer @param name the Device's name, usually some string defined by the manufacturer
@param deviceNode the Device's node, for example "/dev/sda" @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 QString& deviceNode,
const qint64 logicalSize, const qint64 logicalSectorSize,
const qint64 totalLogical, const qint64 totalLogicalSectors,
const QString& iconName, const QString& iconName,
Device::Type type) Device::Type type)
: QObject() : QObject()
, m_Name(name.length() > 0 ? name : i18n("Unknown Device")) , d(d_ptr)
, 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->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. /** Copy constructor for Device.
@ -51,30 +54,31 @@ Device::Device(const QString& name,
*/ */
Device::Device(const Device& other) Device::Device(const Device& other)
: QObject() : QObject()
, m_Name(other.m_Name) , d(std::make_shared<DevicePrivate>())
, 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)
{ {
if (other.m_PartitionTable) d->m_Name = other.d->m_Name;
m_PartitionTable = new PartitionTable(*other.m_PartitionTable); d->m_DeviceNode = other.d->m_DeviceNode;
if (other.m_SmartStatus) d->m_LogicalSectorSize = other.d->m_LogicalSectorSize;
m_SmartStatus = new SmartStatus(*other.m_SmartStatus); 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. */ /** Destructs a Device. */
Device::~Device() Device::~Device()
{ {
delete m_PartitionTable; delete d->m_PartitionTable;
} }
bool Device::operator==(const Device& other) const 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 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()); 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/>.* * 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 #define KPMCORE_DEVICE_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
@ -24,10 +23,13 @@
#include <QString> #include <QString>
#include <QObject> #include <QObject>
#include <memory>
class PartitionTable; class PartitionTable;
class CreatePartitionTableOperation; class CreatePartitionTableOperation;
class CoreBackend; class CoreBackend;
class SmartStatus; class SmartStatus;
class DevicePrivate;
/** A device description. /** A device description.
@ -48,96 +50,66 @@ class LIBKPMCORE_EXPORT Device : public QObject
friend class CoreBackend; friend class CoreBackend;
public: public:
enum Type { enum class Type {
Disk_Device = 0, Unknown_Device,
LVM_Device = 1, /* VG */ Disk_Device,
RAID_Device = 2, /* software RAID device */ LVM_Device, /* VG */
Unknown_Device = 4 SoftwareRAID_Device, /* software RAID device, i.e. mdraid */
FakeRAID_Device, /* fake RAID device, i.e. dmraid */
}; };
protected: 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);
explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Disk_Device);
public: public:
explicit Device(const Device& other); explicit Device(const Device& other);
virtual ~Device(); virtual ~Device();
public:
virtual bool operator==(const Device& other) const; virtual bool operator==(const Device& other) const;
virtual bool operator!=(const Device& other) const; virtual bool operator!=(const Device& other) const;
virtual QString& name() { /**< @return the Device's name, usually some manufacturer string */
return m_Name; /**< @return the Device's name, usually some manufacturer string */ virtual QString& name();
} virtual const QString& name() const;
virtual const QString& name() const { /**< @return the Device's node, for example "/dev/sda" */
return m_Name; /**< @return the Device's name, usually some manufacturer string */ virtual const QString& deviceNode() const;
}
virtual const QString& deviceNode() const { /**< @return the logical sector size the Device uses (would be extent size for e.g. LVM devices) */
return m_DeviceNode; /**< @return the Device's node, for example "/dev/sda" */ virtual qint64 logicalSize() const;
}
virtual PartitionTable* partitionTable() { /**< @return the total number of logical sectors on the device */
return m_PartitionTable; /**< @return the Device's PartitionTable */ virtual qint64 totalLogical() const;
}
virtual const PartitionTable* partitionTable() const { /**< @return the Device's PartitionTable */
return m_PartitionTable; /**< @return the Device's PartitionTable */ virtual PartitionTable* partitionTable();
} virtual const PartitionTable* partitionTable() const;
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;
}
/** /**
* Change the description of the partition table for different one. * Change the description of the partition table for different one.
* The device itself is not changed; use CreatePartitionTableOperation * The device itself is not changed; use CreatePartitionTableOperation
* for that. The Device instance becomes the owner of @p ptable . * for that. The Device instance becomes the owner of @p ptable .
*/ */
virtual void setPartitionTable(PartitionTable* ptable) { virtual void setPartitionTable(PartitionTable* ptable);
m_PartitionTable = ptable;
virtual qint64 capacity() const { /**< @return the Device's capacity in bytes */
return logicalSize() * totalLogical();
} }
virtual qint64 logicalSize() const { /**< @return suggested icon name for this Device */
return m_LogicalSize; virtual const QString& iconName() const;
}
virtual qint64 totalLogical() const { /**< @param name set the new Icon for this Device */
return m_TotalLogical; virtual void setIconName(const QString& name);
}
virtual Device::Type type() const { virtual SmartStatus& smartStatus();
return m_Type; virtual const SmartStatus& smartStatus() const;
}
virtual Device::Type type() const;
virtual QString prettyName() const; virtual QString prettyName() const;
protected: protected:
QString m_Name; std::shared_ptr<DevicePrivate> d;
QString m_DeviceNode;
qint64 m_LogicalSize;
qint64 m_TotalLogical;
PartitionTable* m_PartitionTable;
QString m_IconName;
SmartStatus* m_SmartStatus;
Device::Type m_Type;
}; };
#endif #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) 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -17,6 +17,7 @@
*************************************************************************/ *************************************************************************/
#include "core/diskdevice.h" #include "core/diskdevice.h"
#include "core/device_p.h"
#include "core/partitiontable.h" #include "core/partitiontable.h"
#include "core/smartstatus.h" #include "core/smartstatus.h"
@ -39,14 +40,25 @@
#define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */ #define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */
#endif #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) static qint64 getPhysicalSectorSize(const QString& device_node)
{ {
/* /*
* possible ways of getting the physical sector size for a drive: * possible ways of getting the physical sector size for a drive:
* - ioctl(BLKPBSZGET) -- supported with Linux 2.6.32 and later * - ioctl(BLKPBSZGET) -- supported with Linux 2.6.32 and later
* - /sys/block/sda/queue/physical_block_size * - /sys/block/sda/queue/physical_block_size
* - libblkid from util-linux-ng 2.17 or later * - libblkid from util-linux 2.17 or later (not implemented)
* TODO: implement the blkid method
*/ */
#if defined(BLKPBSZGET) #if defined(BLKPBSZGET)
@ -87,11 +99,46 @@ DiskDevice::DiskDevice(const QString& name,
qint32 cylinders, qint32 cylinders,
qint64 sectorSize, qint64 sectorSize,
const QString& iconName) const QString& iconName)
: Device(name, deviceNode, sectorSize, (static_cast<qint64>(heads) * cylinders * numSectors), iconName, Device::Disk_Device) : Device(std::make_shared<DiskDevicePrivate>(), name, deviceNode, sectorSize, (static_cast<qint64>(heads) * cylinders * numSectors), iconName, Device::Type::Disk_Device)
, m_Heads(heads)
, m_SectorsPerTrack(numSectors)
, m_Cylinders(cylinders)
, m_LogicalSectorSize(sectorSize)
, m_PhysicalSectorSize(getPhysicalSectorSize(deviceNode))
{ {
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) 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * 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/>.* * 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 #define KPMCORE_DISKDEVICE_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
#include "core/device.h" #include "core/device.h"
#include <memory>
#include <QString> #include <QString>
#include <QObject> #include <QObject>
#include <QtGlobal> #include <QtGlobal>
@ -30,6 +32,7 @@ class PartitionTable;
class CreatePartitionTableOperation; class CreatePartitionTableOperation;
class CoreBackend; class CoreBackend;
class SmartStatus; class SmartStatus;
class DiskDevicePrivate;
/** A disk device. /** A disk device.
@ -40,6 +43,7 @@ class SmartStatus;
@see PartitionTable, Partition @see PartitionTable, Partition
@author Volker Lanz <vl@fidra.de> @author Volker Lanz <vl@fidra.de>
*/ */
class LIBKPMCORE_EXPORT DiskDevice : public Device class LIBKPMCORE_EXPORT DiskDevice : public Device
{ {
Q_DISABLE_COPY(DiskDevice) 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()); DiskDevice(const QString& name, const QString& deviceNode, qint32 heads, qint32 numSectors, qint32 cylinders, qint64 sectorSize, const QString& iconName = QString());
public: public:
qint32 heads() const { /**
return m_Heads; /**< @return the number of heads on the Device in CHS notation */ * @return the number of heads on the Device in CHS notation
} */
qint32 cylinders() const { [[deprecated]]
return m_Cylinders; /**< @return the number of cylinders on the Device in CHS notation */ qint32 heads() const;
}
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 */
}
private: /**
qint32 m_Heads; * @return the number of cylinders on the Device in CHS notation
qint32 m_SectorsPerTrack; */
qint32 m_Cylinders; [[deprecated]]
qint64 m_LogicalSectorSize; qint32 cylinders() const;
qint64 m_PhysicalSectorSize;
/**
* @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 #endif

View File

@ -18,38 +18,47 @@
*************************************************************************/ *************************************************************************/
#include "core/fstab.h" #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 <QChar>
#include <QDebug> #include <QDebug>
#include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QRegularExpression> #include <QRegularExpression>
#include <QTemporaryFile>
#include <QTextStream> #include <QTextStream>
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);
static QString findBlkIdDevice(const QString& token, const QString& value); 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) struct FstabEntryPrivate
: m_fsSpec(fsSpec)
, m_mountPoint(mountPoint)
, m_type(type)
, m_dumpFreq(dumpFreq)
, m_passNumber(passNumber)
, m_comment(comment)
{ {
m_options = options.split(QLatin1Char(',')); QString m_fsSpec;
parseFsSpec(m_fsSpec, m_entryType, m_deviceNode); 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;
};
/** FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) :
@param s the new value for the fs_spec field of fstab entry d(std::make_unique<FstabEntryPrivate>())
*/
void FstabEntry::setFsSpec(const QString& s)
{ {
m_fsSpec = s; d->m_fsSpec = fsSpec;
parseFsSpec(m_fsSpec, m_entryType, m_deviceNode); 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 ) FstabEntryList readFstabEntries( const QString& fstabPath )
@ -63,7 +72,7 @@ FstabEntryList readFstabEntries( const QString& fstabPath )
{ {
QString line = rawLine.trimmed(); QString line = rawLine.trimmed();
if ( line.startsWith( QLatin1Char('#') ) || line.isEmpty()) { if ( line.startsWith( QLatin1Char('#') ) || line.isEmpty()) {
fstabEntries.append( { {}, {}, {}, {}, {}, {}, line } ); fstabEntries.push_back( { {}, {}, {}, {}, {}, {}, line } );
continue; continue;
} }
@ -80,27 +89,98 @@ FstabEntryList readFstabEntries( const QString& fstabPath )
// (#) comment (optional). // (#) comment (optional).
switch (splitLine.length()) { switch (splitLine.length()) {
case 4: 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; break;
case 5: 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; break;
case 6: 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; break;
default: default:
fstabEntries.append( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } ); fstabEntries.push_back( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } );
} }
} }
fstabFile.close(); fstabFile.close();
if (fstabEntries.last().entryType() == comment && fstabEntries.last().comment().isEmpty()) if (fstabEntries.back().entryType() == FstabEntry::Type::comment && fstabEntries.back().comment().isEmpty())
fstabEntries.removeLast(); fstabEntries.pop_back();
} }
return fstabEntries; 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 possibleMountPoints(const QString& deviceNode, const QString& fstabPath)
{ {
QStringList mountPoints; QStringList mountPoints;
@ -113,40 +193,37 @@ QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabP
return mountPoints; 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; QString rval;
if (blkid_get_cache(&cache, nullptr) == 0) { #if defined(Q_OS_LINUX)
if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), &cache)) { if (char* c = blkid_evaluate_tag(token, value.toLocal8Bit().constData(), nullptr)) {
rval = QString::fromLocal8Bit(c); rval = QString::fromLocal8Bit(c);
free(c); free(c);
}
blkid_put_cache(cache);
} }
#endif
return rval; 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="))) { if (m_fsSpec.startsWith(QStringLiteral("UUID="))) {
m_entryType = FstabEntryType::uuid; m_entryType = FstabEntry::Type::uuid;
m_deviceNode = findBlkIdDevice(QStringLiteral("UUID"), QString(m_fsSpec).remove(QStringLiteral("UUID="))); m_deviceNode = findBlkIdDevice("UUID", QString(m_fsSpec).remove(QStringLiteral("UUID=")));
} else if (m_fsSpec.startsWith(QStringLiteral("LABEL="))) { } else if (m_fsSpec.startsWith(QStringLiteral("LABEL="))) {
m_entryType = FstabEntryType::label; m_entryType = FstabEntry::Type::label;
m_deviceNode = findBlkIdDevice(QStringLiteral("LABEL"), QString(m_fsSpec).remove(QStringLiteral("LABEL="))); m_deviceNode = findBlkIdDevice("LABEL", QString(m_fsSpec).remove(QStringLiteral("LABEL=")));
} else if (m_fsSpec.startsWith(QStringLiteral("PARTUUID="))) { } else if (m_fsSpec.startsWith(QStringLiteral("PARTUUID="))) {
m_entryType = FstabEntryType::uuid; m_entryType = FstabEntry::Type::uuid;
m_deviceNode = findBlkIdDevice(QStringLiteral("PARTUUID"), QString(m_fsSpec).remove(QStringLiteral("PARTUUID="))); m_deviceNode = findBlkIdDevice("PARTUUID", QString(m_fsSpec).remove(QStringLiteral("PARTUUID=")));
} else if (m_fsSpec.startsWith(QStringLiteral("PARTLABEL="))) { } else if (m_fsSpec.startsWith(QStringLiteral("PARTLABEL="))) {
m_entryType = FstabEntryType::label; m_entryType = FstabEntry::Type::label;
m_deviceNode = findBlkIdDevice(QStringLiteral("PARTLABEL"), QString(m_fsSpec).remove(QStringLiteral("PARTLABEL="))); m_deviceNode = findBlkIdDevice("PARTLABEL", QString(m_fsSpec).remove(QStringLiteral("PARTLABEL=")));
} else if (m_fsSpec.startsWith(QStringLiteral("/"))) { } else if (m_fsSpec.startsWith(QStringLiteral("/"))) {
m_entryType = FstabEntryType::deviceNode; m_entryType = FstabEntry::Type::deviceNode;
m_deviceNode = m_fsSpec; 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) static void writeEntry(QFile& output, const FstabEntry& entry)
{ {
QTextStream s(&output); QTextStream s(&output);
if (entry.entryType() == FstabEntryType::comment) { if (entry.entryType() == FstabEntry::Type::comment) {
s << entry.comment() << "\n"; s << entry.comment() << "\n";
return; return;
} }
@ -177,34 +254,34 @@ static void writeEntry(QFile& output, const FstabEntry& entry)
<< entry.comment() << "\n"; << entry.comment() << "\n";
} }
bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename) bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename)
{ {
bool rval = true; QTemporaryFile out;
const QString newFilename = QStringLiteral("%1.new").arg(filename); out.setAutoRemove(false);
QFile out(newFilename);
if (!out.open(QFile::ReadWrite | QFile::Truncate)) { if (!out.open()) {
qWarning() << "could not open output file " << newFilename; qWarning() << "could not open output file " << out.fileName();
rval = false; return false;
} else { } else {
for (const auto &e : fstabEntries) for (const auto &e : fstabEntries)
writeEntry(out, e); writeEntry(out, e);
out.close(); out.close();
const QString bakFilename = QStringLiteral("%1.bak").arg(filename); 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)) { if ( !(mvCmd.run(-1) && mvCmd.exitCode() == 0) ) {
qWarning() << "could not rename " << filename << " to " << bakFilename; qWarning() << "could not backup " << filename << " to " << bakFilename;
rval = false; return false;
} }
if (rval && !QFile::rename(newFilename, filename)) { ExternalCommand mvCmd2(QStringLiteral("mv"), { out.fileName(), filename } );
qWarning() << "could not rename " << newFilename << " to " << filename;
rval = false; 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -20,10 +20,12 @@
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
#include <memory>
#include <QList> #include <QList>
#include <QString> #include <QString>
enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment }; struct FstabEntryPrivate;
/** Base class for fstab handling. /** Base class for fstab handling.
@ -35,65 +37,88 @@ enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment };
class LIBKPMCORE_EXPORT FstabEntry class LIBKPMCORE_EXPORT FstabEntry
{ {
public: 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()); 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 */ * @return the fs_spec field of fstab entry
} */
const QString& deviceNode() const { const QString& fsSpec() 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 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 setFsSpec(const QString& s);
void setMountPoint(const QString& s) {
m_mountPoint = s; /**< @param s the new value for the mount point */ /**
} * @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 setMountPoint(const QString& s);
}
void setDumpFreq(int s) { /**
m_dumpFreq = s; /**< @param s the new value for the dump frequency */ * @param s the new list with the mount options
} */
void setPassNumber(int s) { void setOptions(const QStringList& s);
m_passNumber = s; /**< @param s the new value for the pass number */
} /**
* @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: private:
QString m_fsSpec; std::shared_ptr<FstabEntryPrivate> d;
QString m_deviceNode;
QString m_mountPoint;
QString m_type;
QStringList m_options;
int m_dumpFreq;
int m_passNumber;
QString m_comment;
FstabEntryType m_entryType;
}; };
typedef QList<FstabEntry> FstabEntryList; typedef QList<FstabEntry> FstabEntryList;
LIBKPMCORE_EXPORT FstabEntryList readFstabEntries(const QString& fstabPath = QStringLiteral("/etc/fstab")); 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 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 #endif

View File

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

View File

@ -25,9 +25,6 @@
#include <QDBusReply> #include <QDBusReply>
#include <QMutex> #include <QMutex>
#include <pwd.h>
#include <unistd.h>
/** Constructs an OperationRunner. /** Constructs an OperationRunner.
@param ostack the OperationStack to act on @param ostack the OperationStack to act on
*/ */
@ -50,15 +47,6 @@ void OperationRunner::run()
bool status = true; bool status = true;
// Disable Plasma removable device automounting // 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; QStringList modules;
QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("sessionBus")); QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("sessionBus"));
QDBusInterface kdedInterface( QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QStringLiteral("org.kde.kded5"), bus ); 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); bool automounter = modules.contains(automounterService);
if (automounter) if (automounter)
kdedInterface.call( QStringLiteral("unloadModule"), automounterService ); kdedInterface.call( QStringLiteral("unloadModule"), automounterService );
seteuid(currentUid);
for (int i = 0; i < numOperations(); i++) { for (int i = 0; i < numOperations(); i++) {
suspendMutex().lock(); suspendMutex().lock();

View File

@ -555,7 +555,7 @@ void OperationStack::addDevice(Device* d)
static bool deviceLessThan(const Device* d1, const Device* d2) static bool deviceLessThan(const Device* d1, const Device* d2)
{ {
// Display alphabetically sorted disk devices above LVM VGs // 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 false;
return d1->deviceNode() <= d2->deviceNode(); return d1->deviceNode() <= d2->deviceNode();

View File

@ -80,10 +80,10 @@ public:
New, /**< from a NewOperation */ New, /**< from a NewOperation */
Copy, /**< from a CopyOperation */ Copy, /**< from a CopyOperation */
Restore, /**< from a RestoreOperation */ Restore, /**< from a RestoreOperation */
StateNone = None, StateNone __attribute__((deprecated("Use Partition::State::None"))) = None,
StateNew = New, StateNew __attribute__((deprecated("Use Partition::State::New"))) = New,
StateCopy = Copy, StateCopy __attribute__((deprecated("Use Partition::State::Copy"))) = Copy,
StateRestore = Restore 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); 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) bool PartitionAlignment::isAligned(const Device& d, const Partition& p, qint64 newFirst, qint64 newLast, bool quiet)
{ {
if (firstDelta(d, p, newFirst) && !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) 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; 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) 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); const DiskDevice& device = dynamic_cast<const DiskDevice&>(d);
if (!parent.isRoot()) { if (!parent.isRoot()) {
Partition* extended = dynamic_cast<Partition*>(&parent); 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); 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) { if (end - start + 1 > 0) {
return true; return true;
} }
@ -319,13 +319,13 @@ Partition* createUnallocated(const Device& device, PartitionNode& parent, qint64
r |= PartitionRole::Logical; r |= PartitionRole::Logical;
// Mark unallocated space in LVM VG as LVM LV so that pasting can be easily disabled (it does not work yet) // 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; r |= PartitionRole::Lvm_Lv;
if (!PartitionTable::getUnallocatedRange(device, parent, start, end)) if (!PartitionTable::getUnallocatedRange(device, parent, start, end))
return nullptr; 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 /** Removes all unallocated children from a PartitionNode
@ -379,7 +379,7 @@ void PartitionTable::insertUnallocated(const Device& d, PartitionNode* p, qint64
qint64 lastEnd = start; 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 // rearranging the sectors of all partitions to keep unallocated space at the end
lastEnd = 0; lastEnd = 0;
std::sort(children().begin(), children().end(), [](const Partition* p1, const Partition* p2) { return p1->deviceNode() < p2->deviceNode(); }); 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 if (d.type() == Device::Type::LVM_Device)
// of the device or the extended partition. {
qint64 parentEnd = lastUsable(); const LvmDevice& lvm = static_cast<const LvmDevice&>(d);
p->insert(createUnallocated(d, *p, lastEnd, lastEnd + lvm.freePE() - 1));
if (!p->isRoot()) {
Partition* extended = dynamic_cast<Partition*>(p);
parentEnd = extended ? extended->lastSector() : -1;
Q_ASSERT(extended);
} }
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) if (!p->isRoot()) {
p->insert(createUnallocated(d, *p, lastEnd, parentEnd)); 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. /** 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) qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t)
{ {
Q_UNUSED(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; return 0;
} }
@ -518,7 +526,7 @@ bool PartitionTable::tableTypeIsReadOnly(TableType l)
*/ */
bool PartitionTable::isSectorBased(const Device& d) const 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); const DiskDevice& diskDevice = dynamic_cast<const DiskDevice&>(d);
if (type() == PartitionTable::msdos) { 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/smartattribute.h"
#include "core/smartstatus.h" #include "core/smartstatus.h"
#include "core/smartattributeparseddata.h"
#include <QLocale> #include <QLocale>
#include <KLocalizedString> #include <KLocalizedString>
#include <KFormat> #include <KFormat>
#include <atasmart.h>
static QString getAttrName(qint32 id); static QString getAttrName(qint32 id);
static QString getAttrDescription(qint32 id); static QString getAttrDescription(qint32 id);
static QString getPrettyValue(quint64 value, qint64 unit); static QString getPrettyValue(quint64 value, SmartAttributeUnit unit);
static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a); static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a);
static QString getRaw(const uint8_t*); static QString getRaw(quint64 raw);
SmartAttribute::SmartAttribute(const SkSmartAttributeParsedData* a) : SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) :
m_Id(a->id), m_Id(a.id()),
m_Name(getAttrName(a->id)), m_Name(getAttrName(a.id())),
m_Desc(getAttrDescription(a->id)), m_Desc(getAttrDescription(a.id())),
m_FailureType(a->prefailure ? PreFailure : OldAge), m_FailureType(a.prefailure() ? FailureType::PreFailure : FailureType::OldAge),
m_UpdateType(a->online ? Online : Offline), m_UpdateType(a.online() ? UpdateType::Online : UpdateType::Offline),
m_Current(a->current_value_valid ? a->current_value : -1), m_Current(a.currentValueValid() ? a.currentValue() : -1),
m_Worst(a->worst_value_valid ? a->worst_value : -1), m_Worst(a.worstValueValid() ? a.worstValue() : -1),
m_Threshold(a->threshold_valid ? a->threshold : -1), m_Threshold(a.thresholdValid() ? a.threshold() : -1),
m_Raw(getRaw(a->raw)), m_Raw(getRaw(a.raw())),
m_Assessment(getAssessment(a)), 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) QString SmartAttribute::assessmentToString(Assessment a)
{ {
switch (a) { switch (a) {
case Failing: case Assessment::Failing:
return xi18nc("@item:intable", "failing"); return xi18nc("@item:intable", "failing");
case HasFailed: case Assessment::HasFailed:
return xi18nc("@item:intable", "has failed"); return xi18nc("@item:intable", "has failed");
case Warning: case Assessment::Warning:
return xi18nc("@item:intable", "warning"); return xi18nc("@item:intable", "warning");
case Good: case Assessment::Good:
return xi18nc("@item:intable", "good"); return xi18nc("@item:intable", "good");
case NotApplicable: case Assessment::NotApplicable:
default: default:
return xi18nc("@item:intable not applicable", "N/A"); return xi18nc("@item:intable not applicable", "N/A");
} }
} }
static QString getPrettyValue(quint64 value, qint64 unit) static QString getPrettyValue(quint64 value, SmartAttributeUnit unit)
{ {
QString rval; QString rval;
switch (unit) { switch (unit) {
case SK_SMART_ATTRIBUTE_UNIT_MSECONDS: case SmartAttributeUnit::Miliseconds:
rval = KFormat().formatDuration(value); rval = KFormat().formatDuration(value);
break; break;
case SK_SMART_ATTRIBUTE_UNIT_SECTORS: case SmartAttributeUnit::Sectors:
rval = xi18ncp("@item:intable", "%1 sector", "%1 sectors", value); rval = xi18ncp("@item:intable", "%1 sector", "%1 sectors", value);
break; break;
case SK_SMART_ATTRIBUTE_UNIT_MKELVIN: case SmartAttributeUnit::Milikelvin:
rval = SmartStatus::tempToString(value); rval = SmartStatus::tempToString(value);
break; break;
case SK_SMART_ATTRIBUTE_UNIT_NONE: case SmartAttributeUnit::None:
rval = QLocale().toString(value); rval = QLocale().toString(value);
break; break;
case SK_SMART_ATTRIBUTE_UNIT_UNKNOWN: case SmartAttributeUnit::Unknown:
default: default:
rval = xi18nc("@item:intable not applicable", "N/A"); rval = xi18nc("@item:intable not applicable", "N/A");
break; break;
@ -214,43 +214,41 @@ static QString getAttrDescription(qint32 id)
return QString(); 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 failed = false;
bool hasFailed = false; bool hasFailed = false;
if (a->prefailure) { if (a.prefailure()) {
if (a->good_now_valid && !a->good_now) if (a.goodNowValid() && !a.goodNow())
failed = true; failed = true;
if (a->good_in_the_past_valid && !a->good_in_the_past) if (a.goodInThePastValid() && !a.goodInThePast())
hasFailed = true; hasFailed = true;
} else if (a->threshold_valid) { } else if (a.thresholdValid()) {
if (a->current_value_valid && a->current_value <= a->threshold) if (a.currentValueValid() && a.currentValue() <= a.threshold())
failed = true; failed = true;
else if (a->worst_value_valid && a->worst_value <= a->threshold) else if (a.worstValueValid() && a.worstValue() <= a.threshold())
hasFailed = true; hasFailed = true;
} }
if (failed) if (failed)
rval = SmartAttribute::Failing; rval = SmartAttribute::Assessment::Failing;
else if (hasFailed) else if (hasFailed)
rval = SmartAttribute::HasFailed; rval = SmartAttribute::Assessment::HasFailed;
else if (a->warn) else if (a.warn())
rval = SmartAttribute::Warning; rval = SmartAttribute::Assessment::Warning;
else if (a->good_now_valid) else if (a.goodNowValid())
rval = SmartAttribute::Good; rval = SmartAttribute::Assessment::Good;
return rval; return rval;
} }
static QString getRaw(const uint8_t* raw) static QString getRaw(quint64 raw)
{ {
QString rval = QStringLiteral("0x"); QString rval = QStringLiteral("0x");
for (qint32 i = 5; i >= 0; i--) rval += QStringLiteral("%1").arg(raw, 12, 16, QLatin1Char('0'));
rval += QStringLiteral("%1").arg(raw[i], 2, 16, QLatin1Char('0'));
return rval; return rval;
} }

View File

@ -15,30 +15,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.* * 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 #define KPMCORE_SMARTATTRIBUTE_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
#include <QString> #include <QString>
struct SkSmartAttributeParsedData; class SmartAttributeParsedData;
class LIBKPMCORE_EXPORT SmartAttribute class LIBKPMCORE_EXPORT SmartAttribute
{ {
public: public:
enum FailureType { enum class FailureType {
PreFailure, PreFailure,
OldAge OldAge
}; };
enum UpdateType { enum class UpdateType {
Online, Online,
Offline Offline
}; };
enum Assessment { enum class Assessment {
NotApplicable, NotApplicable,
Failing, Failing,
HasFailed, HasFailed,
@ -47,7 +46,7 @@ public:
}; };
public: public:
SmartAttribute(const SkSmartAttributeParsedData* a); SmartAttribute(const SmartAttributeParsedData& a);
public: public:
qint32 id() const { qint32 id() const {
@ -104,4 +103,3 @@ private:
}; };
#endif #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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * 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/>.* * 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; @author Caio Carvalho <caiojcarvalho@gmail.com>
class PartitionTable; */
class Report; class SmartParser
class CoreBackendPartitionTable;
class LibPartedDevice : public CoreBackendDevice
{ {
Q_DISABLE_COPY(LibPartedDevice) public:
SmartParser(const QString &device_path);
~SmartParser();
public: public:
LibPartedDevice(const QString& deviceNode); bool init();
~LibPartedDevice();
public: public:
bool open() override; const QString &devicePath() const
bool openExclusive() override; {
bool close() override; return m_DevicePath; /**< @return the device path that SMART must analyse */
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;
} }
SmartDiskInformation *diskInformation() const
{
return m_DiskInformation; /**< @return a reference to parsed disk information */
}
protected:
void loadSmartOutput();
void loadAttributes();
private: 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/smartstatus.h"
#include "core/smartparser.h"
#include "core/smartdiskinformation.h"
#include "core/smartattributeparseddata.h"
#include <KLocalizedString> #include <KLocalizedString>
#include <QDebug> #include <QDebug>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <atasmart.h>
#include <errno.h> #include <errno.h>
SmartStatus::SmartStatus(const QString& device_path) : SmartStatus::SmartStatus(const QString &device_path) :
m_DevicePath(device_path), m_DevicePath(device_path),
m_InitSuccess(false), m_InitSuccess(false),
m_Status(false), m_Status(false),
m_ModelName(), m_ModelName(),
m_Serial(), m_Serial(),
m_Firmware(), m_Firmware(),
m_Overall(Bad), m_Overall(Overall::Bad),
m_SelfTestStatus(Success), m_SelfTestStatus(SelfTestStatus::Success),
m_Temp(0), m_Temp(0),
m_BadSectors(0), m_BadSectors(0),
m_PowerCycles(0), m_PowerCycles(0),
@ -46,148 +49,31 @@ SmartStatus::SmartStatus(const QString& device_path) :
void SmartStatus::update() void SmartStatus::update()
{ {
SkDisk* skDisk = nullptr; SmartParser parser(devicePath());
SkBool skSmartStatus = false;
uint64_t mkelvin = 0;
uint64_t skBadSectors = 0;
uint64_t skPoweredOn = 0;
uint64_t skPowerCycles = 0;
if (sk_disk_open(devicePath().toLocal8Bit().constData(), &skDisk) < 0) { if (!parser.init()) {
qDebug() << "smart disk open failed for " << devicePath() << ": " << strerror(errno); qDebug() << "error during smart output parsing for " << devicePath() << ": " << strerror(errno);
return; return;
} }
if (sk_disk_smart_status(skDisk, &skSmartStatus) < 0) { SmartDiskInformation *disk;
qDebug() << "getting smart status failed for " << devicePath() << ": " << strerror(errno);
sk_disk_free(skDisk); disk = parser.diskInformation();
if (!disk)
return; return;
}
setStatus(skSmartStatus); setStatus(disk->smartStatus());
setModelName(disk->model());
if (sk_disk_smart_read_data(skDisk) < 0) { setFirmware(disk->firmware());
qDebug() << "reading smart data failed for " << devicePath() << ": " << strerror(errno); setSerial(disk->serial());
sk_disk_free(skDisk); setSelfTestStatus(disk->selfTestExecutionStatus());
return; setOverall(disk->overall());
} setTemp(disk->temperature());
setBadSectors(disk->badSectors());
const SkIdentifyParsedData* skIdentify; setPoweredOn(disk->poweredOn());
setPowerCycles(disk->powerCycles());
if (sk_disk_identify_parse(skDisk, &skIdentify) < 0) addAttributes(disk->attributes());
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);
setInitSuccess(true); setInitSuccess(true);
} }
@ -195,40 +81,41 @@ QString SmartStatus::tempToString(quint64 mkelvin)
{ {
const double celsius = (mkelvin - 273150.0) / 1000.0; const double celsius = (mkelvin - 273150.0) / 1000.0;
const double fahrenheit = 9.0 * celsius / 5.0 + 32; 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) QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s)
{ {
switch (s) { switch (s) {
case Aborted: case SelfTestStatus::Aborted:
return xi18nc("@item", "Aborted"); return xi18nc("@item", "Aborted");
case Interrupted: case SelfTestStatus::Interrupted:
return xi18nc("@item", "Interrupted"); return xi18nc("@item", "Interrupted");
case Fatal: case SelfTestStatus::Fatal:
return xi18nc("@item", "Fatal error"); return xi18nc("@item", "Fatal error");
case ErrorUnknown: case SelfTestStatus::ErrorUnknown:
return xi18nc("@item", "Unknown error"); return xi18nc("@item", "Unknown error");
case ErrorEletrical: case SelfTestStatus::ErrorEletrical:
return xi18nc("@item", "Electrical error"); return xi18nc("@item", "Electrical error");
case ErrorServo: case SelfTestStatus::ErrorServo:
return xi18nc("@item", "Servo error"); return xi18nc("@item", "Servo error");
case ErrorRead: case SelfTestStatus::ErrorRead:
return xi18nc("@item", "Read error"); return xi18nc("@item", "Read error");
case ErrorHandling: case SelfTestStatus::ErrorHandling:
return xi18nc("@item", "Handling error"); return xi18nc("@item", "Handling error");
case InProgress: case SelfTestStatus::InProgress:
return xi18nc("@item", "Self test in progress"); return xi18nc("@item", "Self test in progress");
case Success: case SelfTestStatus::Success:
default: default:
return xi18nc("@item", "Success"); return xi18nc("@item", "Success");
} }
@ -238,33 +125,35 @@ QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s)
QString SmartStatus::overallAssessmentToString(Overall o) QString SmartStatus::overallAssessmentToString(Overall o)
{ {
switch (o) { switch (o) {
case Good: case Overall::Good:
return xi18nc("@item", "Healthy"); return xi18nc("@item", "Healthy");
case BadPast: case Overall::BadPast:
return xi18nc("@item", "Has been used outside of its design parameters in the past."); 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."); 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."); 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."); return xi18nc("@item", "Has many bad sectors.");
case Bad: case Overall::Bad:
default: default:
return xi18nc("@item", "Disk failure is imminent. Backup all data!"); 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); for (const SmartAttributeParsedData &at : qAsConst(attr)) {
self->m_Attributes.append(sm); 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/>.* * 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 #define KPMCORE_SMARTSTATUS_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
@ -32,7 +31,7 @@ struct SkDisk;
class LIBKPMCORE_EXPORT SmartStatus class LIBKPMCORE_EXPORT SmartStatus
{ {
public: public:
enum Overall { enum class Overall {
Good, Good,
BadPast, BadPast,
BadSectors, BadSectors,
@ -41,7 +40,7 @@ public:
Bad Bad
}; };
enum SelfTestStatus { enum class SelfTestStatus {
Success, Success,
Aborted, Aborted,
Interrupted, Interrupted,
@ -51,99 +50,123 @@ public:
ErrorServo, ErrorServo,
ErrorRead, ErrorRead,
ErrorHandling, ErrorHandling,
InProgress InProgress = 15,
}; };
public: public:
typedef QList<SmartAttribute> Attributes; typedef QList<SmartAttribute> Attributes;
public: public:
SmartStatus(const QString& device_path); SmartStatus(const QString &device_path);
public: public:
void update(); void update();
const QString& devicePath() const { const QString &devicePath() const
{
return m_DevicePath; return m_DevicePath;
} }
bool isValid() const { bool isValid() const
{
return m_InitSuccess; return m_InitSuccess;
} }
bool status() const { bool status() const
{
return m_Status; return m_Status;
} }
const QString& modelName() const { const QString &modelName() const
{
return m_ModelName; return m_ModelName;
} }
const QString& serial() const { const QString &serial() const
{
return m_Serial; return m_Serial;
} }
const QString& firmware() const { const QString &firmware() const
{
return m_Firmware; return m_Firmware;
} }
quint64 temp() const { quint64 temp() const
{
return m_Temp; return m_Temp;
} }
quint64 badSectors() const { quint64 badSectors() const
{
return m_BadSectors; return m_BadSectors;
} }
quint64 powerCycles() const { quint64 powerCycles() const
{
return m_PowerCycles; return m_PowerCycles;
} }
quint64 poweredOn() const { quint64 poweredOn() const
{
return m_PoweredOn; return m_PoweredOn;
} }
const Attributes& attributes() const { const Attributes &attributes() const
{
return m_Attributes; return m_Attributes;
} }
Overall overall() const { Overall overall() const
{
return m_Overall; return m_Overall;
} }
SelfTestStatus selfTestStatus() const { SelfTestStatus selfTestStatus() const
{
return m_SelfTestStatus; return m_SelfTestStatus;
} }
void addAttributes(QList<SmartAttributeParsedData> attr);
static QString tempToString(quint64 mkelvin); static QString tempToString(quint64 mkelvin);
static QString overallAssessmentToString(Overall o); static QString overallAssessmentToString(Overall o);
static QString selfTestStatusToString(SmartStatus::SelfTestStatus s); static QString selfTestStatusToString(SmartStatus::SelfTestStatus s);
protected: private:
void setStatus(bool s) { void setStatus(bool s)
{
m_Status = s; m_Status = s;
} }
void setModelName(const QString& name) { void setModelName(const QString &name)
{
m_ModelName = name; m_ModelName = name;
} }
void setSerial(const QString& s) { void setSerial(const QString &s)
{
m_Serial = s; m_Serial = s;
} }
void setFirmware(const QString& f) { void setFirmware(const QString &f)
{
m_Firmware = f; m_Firmware = f;
} }
void setTemp(quint64 t) { void setTemp(quint64 t)
{
m_Temp = t; m_Temp = t;
} }
void setInitSuccess(bool b) { void setInitSuccess(bool b)
{
m_InitSuccess = b; m_InitSuccess = b;
} }
void setBadSectors(quint64 s) { void setBadSectors(quint64 s)
{
m_BadSectors = s; m_BadSectors = s;
} }
void setPowerCycles(quint64 p) { void setPowerCycles(quint64 p)
{
m_PowerCycles = p; m_PowerCycles = p;
} }
void setPoweredOn(quint64 t) { void setPoweredOn(quint64 t)
{
m_PoweredOn = t; m_PoweredOn = t;
} }
void setOverall(Overall o) { void setOverall(Overall o)
{
m_Overall = o; m_Overall = o;
} }
void setSelfTestStatus(SelfTestStatus s) { void setSelfTestStatus(SelfTestStatus s)
{
m_SelfTestStatus = s; m_SelfTestStatus = s;
} }
static void callback(SkDisk* skDisk, const SkSmartAttributeParsedData* a, void* user_data);
private: private:
const QString m_DevicePath; const QString m_DevicePath;
bool m_InitSuccess; bool m_InitSuccess;

View File

@ -1,5 +1,6 @@
/************************************************************************* /*************************************************************************
* Copyright (C) 2016 by Chantara Tith <tith.chantara@gmail.com> * * 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * 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/>.* * along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/ *************************************************************************/
#include "core/device_p.h"
#include "core/volumemanagerdevice.h" #include "core/volumemanagerdevice.h"
#include "core/volumemanagerdevice_p.h"
/** Constructs an abstract Volume Manager Device with an empty PartitionTable. /** 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 QString& deviceNode,
const qint64 logicalSize, const qint64 logicalExtentSize,
const qint64 totalLogical, const qint64 totalLogical,
const QString& iconName, const QString& iconName,
Device::Type type) 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(", ")); 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/>.* * 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 #define KPMCORE_VOLUMEMANAGERDEVICE_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
@ -27,6 +26,8 @@
#include <QObject> #include <QObject>
#include <QtGlobal> #include <QtGlobal>
class VolumeManagerDevicePrivate;
/** A Volume Manager of physical devices represented as an abstract device. /** A Volume Manager of physical devices represented as an abstract device.
* *
* VolumeManagerDevice is an abstract device class for volume manager. e.g: LVM, SoftRAID. * 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) Q_DISABLE_COPY(VolumeManagerDevice)
public: public:
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);
VolumeManagerDevice(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device);
/** /**
* @return list of physical device's path that makes up volumeManagerDevice.(e.g: /dev/sda, /dev/sdb1) * @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. * @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. * @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) * @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 * @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: 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; virtual QString prettyDeviceNodeList() const;
@ -90,10 +90,7 @@ public:
* *
* @param n Number of sectors. * @param n Number of sectors.
*/ */
void setTotalLogical(qint64 n) { void setTotalLogical(qint64 n);
Q_ASSERT(n > 0);
m_TotalLogical = n;
}
}; };
#endif #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/hpfs.cpp
fs/iso9660.cpp fs/iso9660.cpp
fs/jfs.cpp fs/jfs.cpp
fs/linuxraidmember.cpp
fs/linuxswap.cpp fs/linuxswap.cpp
fs/luks.cpp fs/luks.cpp
fs/luks2.cpp fs/luks2.cpp
@ -51,6 +52,7 @@ set(FS_LIB_HDRS
fs/hpfs.h fs/hpfs.h
fs/iso9660.h fs/iso9660.h
fs/jfs.h fs/jfs.h
fs/linuxraidmember.h
fs/linuxswap.h fs/linuxswap.h
fs/luks.h fs/luks.h
fs/luks2.h fs/luks2.h

View File

@ -44,7 +44,7 @@ FileSystem::CommandSupportType btrfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType btrfs::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType btrfs::m_GetUUID = FileSystem::cmdSupportNone;
btrfs::btrfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 qint64 btrfs::maxCapacity() const
{ {
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
} }
int btrfs::maxLabelLength() const int btrfs::maxLabelLength() const

View File

@ -39,7 +39,7 @@ FileSystem::CommandSupportType exfat::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType exfat::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_GetUUID = FileSystem::cmdSupportNone;
exfat::exfat(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 qint64 exfat::maxCapacity() const
{ {
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
} }
int exfat::maxLabelLength() const 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 bool exfat::updateUUID(Report& report, const QString& deviceNode) const
{ {
Q_UNUSED(report); Q_UNUSED(report)
Q_UNUSED(deviceNode); Q_UNUSED(deviceNode)
return false; return false;
} }

View File

@ -84,7 +84,7 @@ FileSystem::SupportTool ext2::supportToolName() const
qint64 ext2::maxCapacity() 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 int ext2::maxLabelLength() const

View File

@ -37,7 +37,7 @@ namespace FS
class LIBKPMCORE_EXPORT ext2 : public FileSystem class LIBKPMCORE_EXPORT ext2 : public FileSystem
{ {
public: 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: public:
void init() override; void init() override;

View File

@ -25,13 +25,13 @@
namespace FS namespace FS
{ {
ext3::ext3(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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) bool ext3::create(Report& report, const QString& deviceNode)

View File

@ -25,13 +25,13 @@
namespace FS namespace FS
{ {
ext4::ext4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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) 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; FileSystem::CommandSupportType extended::m_Move = FileSystem::cmdSupportCore;
extended::extended(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 bool f2fs::oldVersion = false; // 1.8.x or older
f2fs::f2fs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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 int f2fs::maxLabelLength() const

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.* * 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 #define KPMCORE_F2FS_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"

View File

@ -87,12 +87,12 @@ FileSystem::SupportTool fat12::supportToolName() const
qint64 fat12::minCapacity() 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 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 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") }); ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") });
if (!cmd.start()) cmd.write(QByteArray(uuid, sizeof(uuid)));
return false; return cmd.start();
if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid))
return false;
return cmd.waitFor(-1);
} }
} }

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.* * 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 #define KPMCORE_FAT12_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
@ -38,7 +37,7 @@ namespace FS
class LIBKPMCORE_EXPORT fat12 : public FileSystem class LIBKPMCORE_EXPORT fat12 : public FileSystem
{ {
public: 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: public:
void init() override; void init() override;
@ -62,10 +61,10 @@ public:
return m_Create; return m_Create;
} }
CommandSupportType supportGrow() const override { CommandSupportType supportGrow() const override {
return m_Grow; return cmdSupportNone;
} }
CommandSupportType supportShrink() const override { CommandSupportType supportShrink() const override {
return m_Shrink; return cmdSupportNone;
} }
CommandSupportType supportMove() const override { CommandSupportType supportMove() const override {
return m_Move; return m_Move;

View File

@ -33,7 +33,7 @@
namespace FS namespace FS
{ {
fat16::fat16(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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) 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/>.* * 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 #define KPMCORE_FAT16_H
#include "fs/fat12.h" #include "fs/fat12.h"
@ -43,6 +42,13 @@ public:
bool create(Report& report, const QString& deviceNode) override; bool create(Report& report, const QString& deviceNode) override;
bool resize(Report& report, const QString& deviceNode, qint64 length) const 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 minCapacity() const override;
qint64 maxCapacity() const override; qint64 maxCapacity() const override;
bool supportToolFound() const override; bool supportToolFound() const override;

View File

@ -26,18 +26,18 @@
namespace FS namespace FS
{ {
fat32::fat32(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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) 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) // 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") }); ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode, QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=67") });
if (!cmd.start()) cmd.write(QByteArray(uuid, sizeof(uuid)));
return false; return cmd.start();
if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid))
return false;
return cmd.waitFor(-1);
} }
} }

View File

@ -1,7 +1,7 @@
/************************************************************************* /*************************************************************************
* Copyright (C) 2012 by Volker Lanz <vl@fidra.de> * * Copyright (C) 2012 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2015 by Teo Mrnjavac <teo@kde.org> * * 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -31,10 +31,12 @@
#include <KLocalizedString> #include <KLocalizedString>
#include <QColor>
#include <QFileInfo> #include <QFileInfo>
#include <QStandardPaths>
#include <QStorageInfo> #include <QStorageInfo>
const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode = const std::vector<QColor> FileSystem::defaultColorCode =
{ {
{ {
QColor( 220,205,175 ), // unknown QColor( 220,205,175 ), // unknown
@ -66,25 +68,40 @@ const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode
QColor( 170,120,255 ), // udf QColor( 170,120,255 ), // udf
QColor( 177,82,69 ), // iso9660 QColor( 177,82,69 ), // iso9660
QColor( 223,39,104 ), // luks2 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 /** Creates a new FileSystem object
@param firstsector the first sector used by this FileSystem on the Device @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 lastsector the last sector used by this FileSystem on the Device
@param sectorsused the number of sectors in use on the FileSystem @param sectorsused the number of sectors in use on the FileSystem
@param l the FileSystem label @param label the FileSystem label
@param t the FileSystem type @param type the FileSystem type
*/ */
FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& l, FileSystem::Type t) : FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type) :
m_Type(t), d(std::make_unique<FileSystemPrivate>())
m_FirstSector(firstsector), {
m_LastSector(lastsector), d->m_Type = type;
m_SectorsUsed(sectorsused), d->m_FirstSector = firstsector;
m_Label(l), d->m_LastSector = lastsector;
m_UUID() 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) 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); return FS::lvm2_pv::getVGName(partitionPath);
if (partitionPath.isEmpty()) // Happens when during initial scan LUKS is closed 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; bool mounted = false;
if (fs->type() == FileSystem::Lvm2_PV) { if (fs->type() == FileSystem::Type::Lvm2_PV) {
mounted = FS::lvm2_pv::getVGName(partitionPath) != QString(); mounted = FS::lvm2_pv::getVGName(partitionPath) != QString();
} else { } else {
mounted = isMounted(partitionPath); 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 */ /** @return the minimum capacity valid for this FileSystem in bytes */
qint64 FileSystem::minCapacity() const 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 */ /** @return the maximum capacity valid for this FileSystem in bytes */
qint64 FileSystem::maxCapacity() const 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 */ /** @return the maximum label length valid for this FileSystem */
@ -390,6 +407,11 @@ QString FileSystem::name(const QStringList& languages) const
return nameForType(type(), languages); 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 */ /** @return a pointer to a QString C array with all FileSystem names */
static const KLocalizedString* typeNames() static const KLocalizedString* typeNames()
{ {
@ -424,7 +446,8 @@ static const KLocalizedString* typeNames()
kxi18nc("@item filesystem name", "udf"), kxi18nc("@item filesystem name", "udf"),
kxi18nc("@item filesystem name", "iso9660"), kxi18nc("@item filesystem name", "iso9660"),
kxi18nc("@item filesystem name", "luks2"), kxi18nc("@item filesystem name", "luks2"),
kxi18nc("@item filesystem name", "fat12") kxi18nc("@item filesystem name", "fat12"),
kxi18nc("@item filesystem name", "linux_raid_member"),
}; };
return s; return s;
@ -435,10 +458,9 @@ static const KLocalizedString* typeNames()
*/ */
QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages) QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages)
{ {
Q_ASSERT(t >= 0); Q_ASSERT(t < Type::__lastType);
Q_ASSERT(t < __lastType);
return typeNames()[t].toString(languages); return typeNames()[static_cast<int>(t)].toString(languages);
} }
/** @param s the name to get the type for /** @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 ) 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) if (typeNames()[i].toString(languages) == s)
return static_cast<FileSystem::Type>(i); return static_cast<FileSystem::Type>(i);
return Unknown; return Type::Unknown;
} }
/** @return a QList of all known types */ /** @return a QList of all known types */
@ -458,8 +480,8 @@ QList<FileSystem::Type> FileSystem::types()
{ {
QList<FileSystem::Type> result; QList<FileSystem::Type> result;
int i = Ext2; // first "real" filesystem int i = static_cast<int>(Type::Ext2); // first "real" filesystem
while (i != __lastType) while (i != static_cast<int>(Type::__lastType))
result.append(static_cast<FileSystem::Type>(i++)); result.append(static_cast<FileSystem::Type>(i++));
return result; return result;
@ -529,9 +551,25 @@ bool FileSystem::unmount(Report& report, const QString& deviceNode)
return false; 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) 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()) if (!cmd.run())
return false; return false;
@ -547,3 +585,53 @@ FileSystem::SupportTool FileSystem::supportToolName() const
{ {
return SupportTool(); 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) 2012 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2015 by Teo Mrnjavac <teo@kde.org> * * 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * 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/>.* * 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 #define KPMCORE_FILESYSTEM_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
#include <QColor>
#include <QList> #include <QList>
#include <QStringList> #include <QStringList>
#include <QString> #include <QString>
#include <QtGlobal> #include <QtGlobal>
#include <QUrl> #include <QUrl>
#include <array> #include <memory>
#include <vector>
class QColor;
class QValidator; class QValidator;
class Device; class Device;
class Report; class Report;
struct FileSystemPrivate;
/** Base class for all FileSystems. /** Base class for all FileSystems.
@ -57,40 +59,41 @@ public:
}; };
/** Supported FileSystem types */ /** Supported FileSystem types */
enum Type { enum Type : int {
Unknown = 0, Unknown,
Extended = 1, Extended,
Ext2 = 2, Ext2,
Ext3 = 3, Ext3,
Ext4 = 4, Ext4,
LinuxSwap = 5, LinuxSwap,
Fat16 = 6, Fat16,
Fat32 = 7, Fat32,
Ntfs = 8, Ntfs,
ReiserFS = 9, ReiserFS,
Reiser4 = 10, Reiser4,
Xfs = 11, Xfs,
Jfs = 12, Jfs,
Hfs = 13, Hfs,
HfsPlus = 14, HfsPlus,
Ufs = 15, Ufs,
Unformatted = 16, Unformatted,
Btrfs = 17, Btrfs,
Hpfs = 18, Hpfs,
Luks = 19, Luks,
Ocfs2 = 20, Ocfs2,
Zfs = 21, Zfs,
Exfat = 22, Exfat,
Nilfs2 = 23, Nilfs2,
Lvm2_PV = 24, Lvm2_PV,
F2fs = 25, F2fs,
Udf = 26, Udf,
Iso9660 = 27, Iso9660,
Luks2 = 28, Luks2,
Fat12 = 29, Fat12,
LinuxRaidMember,
__lastType = 30 __lastType
}; };
/** The type of support for a given FileSystem action */ /** The type of support for a given FileSystem action */
@ -101,15 +104,15 @@ public:
cmdSupportBackend = 4 /**< supported by the backend */ cmdSupportBackend = 4 /**< supported by the backend */
}; };
static const std::array< QColor, __lastType > defaultColorCode; static const std::vector<QColor> defaultColorCode;
Q_DECLARE_FLAGS(CommandSupportTypes, CommandSupportType) Q_DECLARE_FLAGS(CommandSupportTypes, CommandSupportType)
protected: 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: public:
virtual ~FileSystem() {} virtual ~FileSystem();
public: public:
virtual void init() {} virtual void init() {}
@ -196,9 +199,11 @@ public:
* @see nameForType() * @see nameForType()
*/ */
virtual QString name(const QStringList& languages = {}) const; 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 * 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 mount(Report& report, const QString& deviceNode, const QString& mountPoint);
virtual bool unmount(Report& report, const QString& deviceNode); virtual bool unmount(Report& report, const QString& deviceNode);
qint64 firstSector() const { /**< @return the FileSystem's first sector */
return m_FirstSector; /**< @return the FileSystem's first sector */ qint64 firstSector() const;
}
qint64 lastSector() const { /**< @return the FileSystem's last sector */
return m_LastSector; /**< @return the FileSystem's last sector */ qint64 lastSector() const;
}
qint64 length() const { qint64 length() const {
return lastSector() - firstSector() + 1; /**< @return the FileSystem's length */ 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 */ return firstByte() + length() * sectorSize() - 1; /**< @return the FileSystem's last byte */
} }
void setFirstSector(qint64 s) { /**< @param s the new first sector */
m_FirstSector = s; /**< @param s the new first sector */ void setFirstSector(qint64 s);
}
void setLastSector(qint64 s) { /**< @param s the new last sector */
m_LastSector = s; /**< @param s the new last sector */ void setLastSector(qint64 s);
}
void move(qint64 newStartSector); void move(qint64 newStartSector);
const QString& label() const { /**< @return the FileSystem's label */
return m_Label; /**< @return the FileSystem's label */ const QString& label() const;
}
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 */
}
void setSectorSize(qint64 s) { /**< @return the sector size in the underlying Device */
m_SectorSize = s; /**< @param s the new value for sector size */ qint64 sectorSize() const;
}
void setSectorsUsed(qint64 s) { /**< @return the sectors in use on the FileSystem */
m_SectorsUsed = s; /**< @param s the new value for sectors in use */ qint64 sectorsUsed() const;
}
void setLabel(const QString& s) { /**< @return the FileSystem's UUID */
m_Label = s; /**< @param s the new label */ const QString& uuid() const;
}
void setUUID(const QString& s) { /**< @param s the new value for sector size */
m_UUID = s; /**< @param s the new UUID */ 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: protected:
static bool findExternal(const QString& cmdName, const QStringList& args = QStringList(), int exptectedCode = 1); static bool findExternal(const QString& cmdName, const QStringList& args = QStringList(), int exptectedCode = 1);
protected: std::unique_ptr<FileSystemPrivate> d;
FileSystem::Type m_Type;
qint64 m_FirstSector;
qint64 m_LastSector;
qint64 m_SectorSize;
qint64 m_SectorsUsed;
QString m_Label;
QString m_UUID;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(FileSystem::CommandSupportTypes) 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/hpfs.h"
#include "fs/iso9660.h" #include "fs/iso9660.h"
#include "fs/jfs.h" #include "fs/jfs.h"
#include "fs/linuxraidmember.h"
#include "fs/linuxswap.h" #include "fs/linuxswap.h"
#include "fs/luks.h" #include "fs/luks.h"
#include "fs/luks2.h" #include "fs/luks2.h"
@ -61,36 +62,37 @@ void FileSystemFactory::init()
qDeleteAll(m_FileSystems); qDeleteAll(m_FileSystems);
m_FileSystems.clear(); m_FileSystems.clear();
m_FileSystems.insert(FileSystem::Btrfs, new FS::btrfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Btrfs, new FS::btrfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Exfat, new FS::exfat(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Exfat, new FS::exfat(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ext2, new FS::ext2(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Ext2, new FS::ext2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ext3, new FS::ext3(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Ext3, new FS::ext3(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ext4, new FS::ext4(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Ext4, new FS::ext4(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Extended, new FS::extended(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Extended, new FS::extended(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::F2fs, new FS::f2fs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::F2fs, new FS::f2fs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Fat12, new FS::fat12(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Fat12, new FS::fat12(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Fat16, new FS::fat16(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Fat16, new FS::fat16(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Fat32, new FS::fat32(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Fat32, new FS::fat32(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Hfs, new FS::hfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Hfs, new FS::hfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::HfsPlus, new FS::hfsplus(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::HfsPlus, new FS::hfsplus(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Hpfs, new FS::hpfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Hpfs, new FS::hpfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Iso9660, new FS::iso9660(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Iso9660, new FS::iso9660(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Jfs, new FS::jfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Jfs, new FS::jfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::LinuxRaidMember, new FS::linuxraidmember(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Luks, new FS::luks(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Luks2, new FS::luks2(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Luks, new FS::luks(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Lvm2_PV, new FS::lvm2_pv(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Luks2, new FS::luks2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Nilfs2, new FS::nilfs2(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Lvm2_PV, new FS::lvm2_pv(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ntfs, new FS::ntfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Nilfs2, new FS::nilfs2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ocfs2, new FS::ocfs2(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Ntfs, new FS::ntfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::ReiserFS, new FS::reiserfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Ocfs2, new FS::ocfs2(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Reiser4, new FS::reiser4(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::ReiserFS, new FS::reiserfs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Udf, new FS::udf(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Reiser4, new FS::reiser4(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Ufs, new FS::ufs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Udf, new FS::udf(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Unformatted, new FS::unformatted(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Ufs, new FS::ufs(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Unknown, new FS::unknown(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Unformatted, new FS::unformatted(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Xfs, new FS::xfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Unknown, new FS::unknown(-1, -1, -1, QString()));
m_FileSystems.insert(FileSystem::Zfs, new FS::zfs(-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()) for (const auto &fs : FileSystemFactory::map())
fs->init(); fs->init();
@ -111,36 +113,37 @@ FileSystem* FileSystemFactory::create(FileSystem::Type t, qint64 firstsector, qi
FileSystem* fs = nullptr; FileSystem* fs = nullptr;
switch (t) { switch (t) {
case FileSystem::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break;
case FileSystem::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::LinuxRaidMember: fs = new FS::linuxraidmember(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break; case FileSystem::Type::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break;
case FileSystem::Zfs: fs = new FS::zfs(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; default: break;
} }

View File

@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.* * 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 #define KPMCORE_FILESYSTEMFACTORY_H
#include "fs/filesystem.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; FileSystem::CommandSupportType hfs::m_Backup = FileSystem::cmdSupportNone;
hfs::hfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 int hfs::maxLabelLength() const

View File

@ -35,7 +35,7 @@ FileSystem::CommandSupportType hfsplus::m_Copy = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType hfsplus::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_Backup = FileSystem::cmdSupportNone;
hfsplus::hfsplus(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 qint64 hfsplus::maxCapacity() const
{ {
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
} }
int hfsplus::maxLabelLength() const int hfsplus::maxLabelLength() const

View File

@ -37,12 +37,12 @@ FileSystem::CommandSupportType hpfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType hpfs::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_GetUUID = FileSystem::cmdSupportNone;
hpfs::hpfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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) : 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; FileSystem::CommandSupportType jfs::m_SetLabel = FileSystem::cmdSupportNone;
jfs::jfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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 int jfs::maxLabelLength() const
@ -96,7 +96,7 @@ qint64 jfs::readUsedCapacity(const QString& deviceNode) const
{ {
ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode); 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; qint64 blockSize = -1;
QRegularExpression re(QStringLiteral("Block Size: (\\d+)")); QRegularExpression re(QStringLiteral("Block Size: (\\d+)"));
QRegularExpressionMatch reBlockSize = re.match(cmd.output()); 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; FileSystem::CommandSupportType linuxswap::m_UpdateUUID = FileSystem::cmdSupportNone;
linuxswap::linuxswap(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 bool linuxswap::resize(Report& report, const QString& deviceNode, qint64 length) const
{ {
Q_UNUSED(length); Q_UNUSED(length)
const QString label = readLabel(deviceNode); const QString label = readLabel(deviceNode);
const QString uuid = readUUID(deviceNode); const QString uuid = readUUID(deviceNode);
@ -145,14 +145,14 @@ QString linuxswap::unmountTitle() const
} }
bool linuxswap::canMount(const QString& deviceNode, const QString& mountPoint) 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 // linux swap doesn't require mount point to activate
return mountPoint != QStringLiteral("/"); return mountPoint != QStringLiteral("/");
} }
bool linuxswap::mount(Report& report, const QString& deviceNode, const QString& mountPoint) bool linuxswap::mount(Report& report, const QString& deviceNode, const QString& mountPoint)
{ {
Q_UNUSED(mountPoint); Q_UNUSED(mountPoint)
ExternalCommand cmd(report, QStringLiteral("swapon"), { deviceNode }); ExternalCommand cmd(report, QStringLiteral("swapon"), { deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0; return cmd.run(-1) && cmd.exitCode() == 0;
} }

View File

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

View File

@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.* * 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 #define KPMCORE_LUKS_H
#include "util/libpartitionmanagerexport.h" #include "util/libpartitionmanagerexport.h"
@ -26,11 +25,11 @@
#include "fs/filesystem.h" #include "fs/filesystem.h"
#include <QtGlobal> #include <QtGlobal>
#include <QWidget>
class Report; class Report;
class QString; class QString;
class QWidget;
namespace FS namespace FS
{ {
@ -40,10 +39,10 @@ namespace FS
class LIBKPMCORE_EXPORT luks : public FileSystem class LIBKPMCORE_EXPORT luks : public FileSystem
{ {
public: 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; ~luks() override;
enum KeyLocation { enum class KeyLocation {
unknown, unknown,
dmcrypt, dmcrypt,
keyring keyring
@ -225,7 +224,7 @@ protected:
qint64 m_PayloadSize; qint64 m_PayloadSize;
QString m_outerUuid; 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) 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) if (m_isCryptOpen && m_innerFs)
return m_innerFs->type(); return m_innerFs->type();
return FileSystem::Luks2; return FileSystem::Type::Luks2;
} }
bool luks2::create(Report& report, const QString& deviceNode) 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("--type"), QStringLiteral("luks2"),
QStringLiteral("luksFormat"), QStringLiteral("luksFormat"),
deviceNode }); deviceNode });
if (!( createCmd.start(-1) && if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') &&
createCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && createCmd.start(-1) && createCmd.exitCode() == 0))
createCmd.waitFor() && createCmd.exitCode() == 0))
{ {
return false; return false;
} }
@ -68,7 +67,7 @@ bool luks2::create(Report& report, const QString& deviceNode)
deviceNode, deviceNode,
suggestedMapperName(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; return false;
setPayloadSize(); setPayloadSize();
@ -95,13 +94,13 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength)
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
cryptResizeCmd.start(-1); if (m_KeyLocation == KeyLocation::keyring) {
if (m_KeyLocation == keyring) {
if (m_passphrase.isEmpty()) if (m_passphrase.isEmpty())
return false; return false;
cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
} }
cryptResizeCmd.waitFor(); if (!cryptResizeCmd.start(-1))
return false;
if ( cryptResizeCmd.exitCode() == 0 ) if ( cryptResizeCmd.exitCode() == 0 )
return m_innerFs->resize(report, mapperName(), m_PayloadSize); 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("--size"), QString::number(m_PayloadSize / 512), // FIXME, LUKS2 can have different sector sizes
QStringLiteral("resize"), mapperName() }); QStringLiteral("resize"), mapperName() });
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
cryptResizeCmd.start(-1); if (m_KeyLocation == KeyLocation::keyring) {
if (m_KeyLocation == keyring) {
if (m_passphrase.isEmpty()) if (m_passphrase.isEmpty())
return false; return false;
cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
} }
cryptResizeCmd.waitFor(); if (!cryptResizeCmd.start(-1))
return false;
if ( cryptResizeCmd.exitCode() == 0 ) if ( cryptResizeCmd.exitCode() == 0 )
return true; return true;
} }
@ -127,16 +126,16 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength)
luks::KeyLocation luks2::keyLocation() luks::KeyLocation luks2::keyLocation()
{ {
m_KeyLocation = unknown; m_KeyLocation = KeyLocation::unknown;
ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() }); ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() });
if (statusCmd.run(-1) && statusCmd.exitCode() == 0) { if (statusCmd.run(-1) && statusCmd.exitCode() == 0) {
QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)")); QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)"));
QRegularExpressionMatch rem = re.match(statusCmd.output()); QRegularExpressionMatch rem = re.match(statusCmd.output());
if (rem.hasMatch()) { if (rem.hasMatch()) {
if (rem.captured(1) == QStringLiteral("keyring")) if (rem.captured(1) == QStringLiteral("keyring"))
m_KeyLocation = keyring; m_KeyLocation = KeyLocation::keyring;
else if (rem.captured(1) == QStringLiteral("dm-crypt")) 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, lvm2_pv::lvm2_pv(qint64 firstsector, qint64 lastsector,
qint64 sectorsused, const QString& label) 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_PESize(0)
, m_TotalPE(0) , m_TotalPE(0)
, m_AllocatedPE(0) , m_AllocatedPE(0)
@ -99,7 +99,7 @@ FileSystem::SupportTool lvm2_pv::supportToolName() const
qint64 lvm2_pv::maxCapacity() 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 qint64 lvm2_pv::readUsedCapacity(const QString& deviceNode) const
@ -270,10 +270,10 @@ QList<LvmPV> lvm2_pv::getPVinNode(const PartitionNode* parent)
partitions.append(getPVinNode(node)); partitions.append(getPVinNode(node));
// FIXME: reenable newly created PVs (before applying) once everything works // 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)); 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)); 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) LvmPV::LvmPV(const QString vgName, const Partition* p, bool isLuks)
: m_vgName(vgName) : m_vgName(vgName)

View File

@ -62,7 +62,22 @@ private:
}; };
namespace LVM { 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 namespace FS

View File

@ -47,7 +47,7 @@ FileSystem::CommandSupportType nilfs2::m_UpdateUUID = FileSystem::cmdSupportNone
FileSystem::CommandSupportType nilfs2::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_GetUUID = FileSystem::cmdSupportNone;
nilfs2::nilfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 qint64 nilfs2::maxCapacity() const
{ {
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
} }
int nilfs2::maxLabelLength() const int nilfs2::maxLabelLength() const

View File

@ -50,7 +50,7 @@ FileSystem::CommandSupportType ntfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType ntfs::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_GetUUID = FileSystem::cmdSupportNone;
ntfs::ntfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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 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) bool ntfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel)
{ {
ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }); ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }, QProcess::SeparateChannels);
writeCmd.setProcessChannelMode(QProcess::SeparateChannels);
if (!writeCmd.run(-1)) if (!writeCmd.run(-1))
return false; 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 bool ntfs::updateUUID(Report& report, const QString& deviceNode) const
{ {
Q_UNUSED(report); Q_UNUSED(report)
ExternalCommand cmd(QStringLiteral("ntfslabel"), { QStringLiteral("--new-serial"), deviceNode }); ExternalCommand cmd(QStringLiteral("ntfslabel"), { QStringLiteral("--new-serial"), deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0; 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") }); 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()) { 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); 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; return false;
} }
cmd.write(QByteArray(s, sizeof(s)));
cmd.waitFor(-1);
// Also update backup NTFS boot sector located at the end of the partition // 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 // NOTE: this should fail if filesystem does not span the whole partition
qint64 pos = (lastSector() - firstSector()) * sectorSize() + 28; 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) }); 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()) { 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); 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; 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); 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; FileSystem::CommandSupportType ocfs2::m_GetUUID = FileSystem::cmdSupportNone;
ocfs2::ocfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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 qint64 ocfs2::readUsedCapacity(const QString& deviceNode) const
{ {
Q_UNUSED(deviceNode); Q_UNUSED(deviceNode)
return -1; return -1;
} }
@ -113,15 +113,12 @@ bool ocfs2::create(Report& report, const QString& deviceNode)
{ {
ExternalCommand cmd(report, QStringLiteral("mkfs.ocfs2"), { deviceNode }); ExternalCommand cmd(report, QStringLiteral("mkfs.ocfs2"), { deviceNode });
if (cmd.start()) cmd.write("y\n");
{ if (!cmd.start())
cmd.write("y\n");
cmd.waitFor(-1);
return cmd.exitCode() == 0;
}
else
return false; return false;
return cmd.exitCode() == 0;
} }
bool ocfs2::resize(Report& report, const QString& deviceNode, qint64 length) const 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; FileSystem::CommandSupportType reiser4::m_Backup = FileSystem::cmdSupportNone;
reiser4::reiser4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 // looks like it's actually unknown. see
// http://en.wikipedia.org/wiki/Comparison_of_file_systems // 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 int reiser4::maxLabelLength() const

View File

@ -42,7 +42,7 @@ FileSystem::CommandSupportType reiserfs::m_UpdateUUID = FileSystem::cmdSupportNo
FileSystem::CommandSupportType reiserfs::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_GetUUID = FileSystem::cmdSupportNone;
reiserfs::reiserfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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 int reiserfs::maxLabelLength() const
@ -154,15 +154,15 @@ bool reiserfs::resize(Report& report, const QString& deviceNode, qint64 length)
ExternalCommand cmd(report, QStringLiteral("resize_reiserfs"), ExternalCommand cmd(report, QStringLiteral("resize_reiserfs"),
{ deviceNode, QStringLiteral("-q"), QStringLiteral("-s"), QString::number(length) }); { deviceNode, QStringLiteral("-q"), QStringLiteral("-s"), QString::number(length) });
bool rval = cmd.start(-1); bool rval = cmd.write(QByteArrayLiteral("y\n"));
if (!rval) if (!rval)
return false; return false;
if (cmd.write("y\n", 2) != 2) if (!cmd.start(-1))
return false; 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 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; bool udf::oldMkudffsVersion = false;
udf::udf(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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; FileSystem::CommandSupportType ufs::m_Backup = FileSystem::cmdSupportCore;
ufs::ufs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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; FileSystem::CommandSupportType unformatted::m_Create = FileSystem::cmdSupportFileSystem;
unformatted::unformatted(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 namespace FS
{ {
unknown::unknown(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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; FileSystem::CommandSupportType xfs::m_SetLabel = FileSystem::cmdSupportNone;
xfs::xfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 qint64 xfs::maxCapacity() const
{ {
return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
} }
int xfs::maxLabelLength() const int xfs::maxLabelLength() const

View File

@ -40,7 +40,7 @@ FileSystem::CommandSupportType zfs::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType zfs::m_GetUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_GetUUID = FileSystem::cmdSupportNone;
zfs::zfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : 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 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 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 bool zfs::remove(Report& report, const QString& deviceNode) const

View File

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

View File

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

View File

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

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