From 9563b2efc798e2dea32e08bb96f8d8b2230a8556 Mon Sep 17 00:00:00 2001 From: Teo Mrnjavac Date: Thu, 21 Aug 2014 17:50:37 +0200 Subject: [PATCH] WIP: new prepare viewmodule, with free space check using libparted. --- src/modules/prepare/CMakeLists.txt | 19 ++ .../prepare/CMakeModules/FindLIBPARTED.cmake | 57 +++++ src/modules/prepare/PreparePage.cpp | 45 ++++ src/modules/prepare/PreparePage.h | 34 +++ src/modules/prepare/PrepareViewStep.cpp | 207 ++++++++++++++++++ src/modules/prepare/PrepareViewStep.h | 70 ++++++ src/modules/prepare/module.desc | 5 + src/modules/prepare/partman_devices.c | 137 ++++++++++++ src/modules/prepare/partman_devices.h | 24 ++ src/modules/prepare/prepare.conf | 2 + 10 files changed, 600 insertions(+) create mode 100644 src/modules/prepare/CMakeLists.txt create mode 100644 src/modules/prepare/CMakeModules/FindLIBPARTED.cmake create mode 100644 src/modules/prepare/PreparePage.cpp create mode 100644 src/modules/prepare/PreparePage.h create mode 100644 src/modules/prepare/PrepareViewStep.cpp create mode 100644 src/modules/prepare/PrepareViewStep.h create mode 100644 src/modules/prepare/module.desc create mode 100644 src/modules/prepare/partman_devices.c create mode 100644 src/modules/prepare/partman_devices.h create mode 100644 src/modules/prepare/prepare.conf diff --git a/src/modules/prepare/CMakeLists.txt b/src/modules/prepare/CMakeLists.txt new file mode 100644 index 000000000..a64f7f70e --- /dev/null +++ b/src/modules/prepare/CMakeLists.txt @@ -0,0 +1,19 @@ +include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules ) +find_package( LIBPARTED REQUIRED ) + +set_source_files_properties( partman_devices.c PROPERTIES LANGUAGE CXX ) + +calamares_add_plugin( prepare + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + PrepareViewStep.cpp + PreparePage.cpp + partman_devices.c + UI + LINK_LIBRARIES + calamaresui + ${LIBPARTED_LIBS} + SHARED_LIB +) diff --git a/src/modules/prepare/CMakeModules/FindLIBPARTED.cmake b/src/modules/prepare/CMakeModules/FindLIBPARTED.cmake new file mode 100644 index 000000000..97e7d9758 --- /dev/null +++ b/src/modules/prepare/CMakeModules/FindLIBPARTED.cmake @@ -0,0 +1,57 @@ +# Copyright (C) 2008,2010,2011 by Volker Lanz +# +# 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_LIBRARY} ${LIBPARTED_FS_RESIZE_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) diff --git a/src/modules/prepare/PreparePage.cpp b/src/modules/prepare/PreparePage.cpp new file mode 100644 index 000000000..46f7445fa --- /dev/null +++ b/src/modules/prepare/PreparePage.cpp @@ -0,0 +1,45 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "PreparePage.h" + +#include +#include + + +PreparePage::PreparePage( QWidget* parent ) + : QWidget() +{ + QBoxLayout *mainLayout = new QVBoxLayout; + setLayout( mainLayout ); + + QLabel* text = new QLabel( tr( "For best results, please ensure that this " + "computer:" ), this ); + text->setAlignment( Qt::AlignCenter ); + + mainLayout->addStretch(); + mainLayout->addWidget( text ); + mainLayout->addStretch(); +} + + +void +PreparePage::init() +{ + +} diff --git a/src/modules/prepare/PreparePage.h b/src/modules/prepare/PreparePage.h new file mode 100644 index 000000000..6ee64c49a --- /dev/null +++ b/src/modules/prepare/PreparePage.h @@ -0,0 +1,34 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef PREPAREPAGE_H +#define PREPAREPAGE_H + +#include + +class PreparePage : public QWidget +{ + Q_OBJECT +public: + explicit PreparePage( QWidget* parent = nullptr ); + + void init(); + +}; + +#endif // PREPAREPAGE_H diff --git a/src/modules/prepare/PrepareViewStep.cpp b/src/modules/prepare/PrepareViewStep.cpp new file mode 100644 index 000000000..4a1774a6e --- /dev/null +++ b/src/modules/prepare/PrepareViewStep.cpp @@ -0,0 +1,207 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "PrepareViewStep.h" + +#include "PreparePage.h" +#include "partman_devices.h" + +#include "widgets/QtWaitingSpinner.h" +#include "utils/CalamaresUtilsGui.h" +#include "utils/Logger.h" + +#include +#include + +PrepareViewStep::PrepareViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_widget( new QWidget() ) + , m_actualWidget( new PreparePage() ) + , m_nextEnabled( false ) + , m_requiredSpaceGB( -1 ) +{ + QBoxLayout* mainLayout = new QHBoxLayout; + m_widget->setLayout( mainLayout ); + CalamaresUtils::unmarginLayout( mainLayout ); + + QWidget* waitingWidget = new QWidget; + { + QBoxLayout* waitingLayout = new QVBoxLayout; + waitingWidget->setLayout( waitingLayout ); + waitingLayout->addStretch(); + QBoxLayout* pbLayout = new QHBoxLayout; + waitingLayout->addLayout( pbLayout ); + pbLayout->addStretch(); + + QtWaitingSpinner* spnr = new QtWaitingSpinner(); + pbLayout->addWidget( spnr ); + + pbLayout->addStretch(); + + QLabel* waitingLabel = new QLabel( "Gathering system information..." ); + + int spnrSize = waitingLabel->fontMetrics().height() * 4; + spnr->setFixedSize( spnrSize, spnrSize ); + spnr->setRadius( spnrSize / 2 ); + spnr->setLength( spnrSize / 2 ); + spnr->setWidth( spnrSize / 8 ); + spnr->start(); + + waitingLabel->setAlignment( Qt::AlignCenter); + waitingLayout->addSpacing( spnrSize / 2 ); + waitingLayout->addWidget( waitingLabel ); + waitingLayout->addStretch(); + + mainLayout->addWidget( waitingWidget ); + + CalamaresUtils::unmarginLayout( waitingLayout ); + } + + QTimer* timer = new QTimer; + timer->setSingleShot( true ); + connect( timer, &QTimer::timeout, + [=]() + { + bool bigEnough, hasPower, hasInternet; + qint64 requiredSpaceB = m_requiredSpaceGB * 1073741824L; /*powers of 2*/ + cDebug() << "Need at least bytes:" << requiredSpaceB; + bigEnough = checkBigEnough( requiredSpaceB ); + hasPower = checkHasPower(); + hasInternet = checkHasInternet(); + cDebug() << "bigEnough, hasPower, hasInternet: " + << bigEnough << hasPower << hasInternet; + + m_actualWidget->init(); + m_widget->layout()->removeWidget( waitingWidget ); + waitingWidget->deleteLater(); + m_widget->layout()->addWidget( m_actualWidget ); + m_nextEnabled = true; + emit nextStatusChanged( m_nextEnabled ); + timer->deleteLater(); + } ); + timer->start( 0 ); + + emit nextStatusChanged( true ); +} + + +PrepareViewStep::~PrepareViewStep() +{ + if ( m_widget && m_widget->parent() == nullptr ) + m_widget->deleteLater(); +} + + +QString +PrepareViewStep::prettyName() const +{ + return tr( "Prepare" ); +} + + +QWidget* +PrepareViewStep::widget() +{ + return m_widget; +} + + +void +PrepareViewStep::next() +{ + emit done(); +} + + +void +PrepareViewStep::back() +{} + + +bool +PrepareViewStep::isNextEnabled() const +{ + return m_nextEnabled; +} + + +bool +PrepareViewStep::isAtBeginning() const +{ + return true; +} + + +bool +PrepareViewStep::isAtEnd() const +{ + return true; +} + + +QList< Calamares::job_ptr > +PrepareViewStep::jobs() const +{ + return QList< Calamares::job_ptr >(); +} + + +void +PrepareViewStep::onLeave() +{ +} + + +void +PrepareViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ + if ( configurationMap.contains( "requiredSpace" ) && + configurationMap.value( "requiredSpace" ).type() == QVariant::Double ) + { + bool ok = false; + m_requiredSpaceGB = configurationMap.value( "requiredSpace" ).toDouble( &ok ); + if ( !ok ) + m_requiredSpaceGB = 3.; + } + else + { + m_requiredSpaceGB = 3.; + } +} + + +bool +PrepareViewStep::checkBigEnough( qint64 requiredSpace ) +{ + return check_big_enough( requiredSpace ); +} + + +bool +PrepareViewStep::checkHasPower() +{ + return false; +} + + +bool +PrepareViewStep::checkHasInternet() +{ + return false; +} + diff --git a/src/modules/prepare/PrepareViewStep.h b/src/modules/prepare/PrepareViewStep.h new file mode 100644 index 000000000..7d30f0ec4 --- /dev/null +++ b/src/modules/prepare/PrepareViewStep.h @@ -0,0 +1,70 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef PREPAREPAGEPLUGIN_H +#define PREPAREPAGEPLUGIN_H + +#include + +#include "viewpages/ViewStep.h" +#include "PluginDllMacro.h" + +class PreparePage; + +class PLUGINDLLEXPORT PrepareViewStep : public Calamares::ViewStep +{ + Q_OBJECT + Q_PLUGIN_METADATA( IID "calamares.ViewModule/1.0" ) + + Q_INTERFACES( Calamares::ViewStep ) + +public: + explicit PrepareViewStep( QObject* parent = nullptr ); + virtual ~PrepareViewStep(); + + QString prettyName() const override; + + QWidget* widget() override; + + void next() override; + void back() override; + + bool isNextEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + + QList< Calamares::job_ptr > jobs() const override; + + void onLeave() override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + bool checkBigEnough( qint64 requiredSpace ); + bool checkHasPower(); + bool checkHasInternet(); + + QWidget* m_widget; + qreal m_requiredSpaceGB; + + PreparePage* m_actualWidget; + bool m_nextEnabled; +}; + +#endif // PREPAREPAGEPLUGIN_H diff --git a/src/modules/prepare/module.desc b/src/modules/prepare/module.desc new file mode 100644 index 000000000..4c7a9fcc1 --- /dev/null +++ b/src/modules/prepare/module.desc @@ -0,0 +1,5 @@ +--- +type: "view" #core or view +name: "prepare" #the module name. must be unique and same as the parent directory +interface: "qtplugin" #can be: qtplugin, python, process, ... +load: "libcalamares_viewmodule_prepare.so" diff --git a/src/modules/prepare/partman_devices.c b/src/modules/prepare/partman_devices.c new file mode 100644 index 000000000..98d50fd9c --- /dev/null +++ b/src/modules/prepare/partman_devices.c @@ -0,0 +1,137 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Based on parted_devices.c, from partman-base. + * + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "partman_devices.h" + +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +/* from */ +#define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ +#endif /* __linux__ */ + +#ifdef __FreeBSD_kernel__ +#include +#include +#endif + +#include + +#if defined(__linux__) +static int +is_cdrom(const char *path) +{ + int fd; + int ret; + + fd = open(path, O_RDONLY | O_NONBLOCK); + ret = ioctl(fd, CDROM_GET_CAPABILITY, NULL); + close(fd); + + if (ret >= 0) + return 1; + else + return 0; +} +#elif defined(__FreeBSD_kernel__) /* !__linux__ */ +static int +is_cdrom(const char *path) +{ + int fd; + + fd = open(path, O_RDONLY | O_NONBLOCK); + ioctl(fd, CDIOCCAPABILITY, NULL); + close(fd); + + if (errno != EBADF && errno != ENOTTY) + return 1; + else + return 0; +} +#else /* !__linux__ && !__FreeBSD_kernel__ */ +#define is_cdrom(path) 0 +#endif + +#if defined(__linux__) +static int +is_floppy(const char *path) +{ + return (strstr(path, "/dev/floppy") != NULL || + strstr(path, "/dev/fd") != NULL); +} +#elif defined(__FreeBSD_kernel__) /* !__linux__ */ +static int +is_floppy(const char *path) +{ + return (strstr(path, "/dev/fd") != NULL); +} +#else /* !__linux__ && !__FreeBSD_kernel__ */ +#define is_floppy(path) 0 +#endif + +static long long +process_device(PedDevice *dev) +{ + if (dev->read_only) + return -1; + if (is_cdrom(dev->path) || is_floppy(dev->path)) + return -1; + /* Exclude compcache (http://code.google.com/p/compcache/) */ + if (strstr(dev->path, "/dev/ramzswap") != NULL || + strstr(dev->path, "/dev/zram") != NULL) + return -1; + return dev->length * dev->sector_size; +} + +int +check_big_enough(long long required_space) +{ + PedDevice *dev; + ped_exception_fetch_all(); + ped_device_probe_all(); + + bool big_enough = false; + for (dev = NULL; NULL != (dev = ped_device_get_next(dev));) + { + long long dev_size = process_device(dev); + if (dev_size > required_space) + { + big_enough = true; + break; + } + } + ped_device_free_all(); + + return big_enough; +} + +/* +Local variables: +indent-tabs-mode: nil +c-file-style: "linux" +c-font-lock-extra-types: ("Ped\\sw+") +End: +*/ diff --git a/src/modules/prepare/partman_devices.h b/src/modules/prepare/partman_devices.h new file mode 100644 index 000000000..8bc19e58b --- /dev/null +++ b/src/modules/prepare/partman_devices.h @@ -0,0 +1,24 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef PARTMAN_DEVICES_H +#define PARTMAN_DEVICES_H + +int check_big_enough(long long required_space); + +#endif // PARTMAN_DEVICES_H diff --git a/src/modules/prepare/prepare.conf b/src/modules/prepare/prepare.conf new file mode 100644 index 000000000..ee307d556 --- /dev/null +++ b/src/modules/prepare/prepare.conf @@ -0,0 +1,2 @@ +--- +requiredSpace: 5.5 \ No newline at end of file