diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..cb793f994 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "src/libcalamares/partitionmanager"] + path = src/libcalamares/partitionmanager + url = https://github.com/calamares/partitionmanager.git + branch = calamares diff --git a/CMakeLists.txt b/CMakeLists.txt index 781e0b721..1faf47f9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ file( COPY CalamaresAddLibrary.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) set( CALAMARES_LIBRARIES calamareslib ) add_subdirectory( src ) +add_subdirectory( tests ) # Add all targets to the build-tree export set set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" ) diff --git a/README.md b/README.md index 3abce9d94..ed9aec352 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Distribution-independent installer framework ### Building ``` +$ git submodule init +$ git submodule update $ mkdir build $ cd build $ cmake -DCMAKE_BUILD_TYPE=Debug .. diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 28531e7f3..c6e4bfbc4 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -1,5 +1,7 @@ project( calamareslib ) +add_subdirectory( partitionmanager/calamares ) + add_definitions( ${QT_DEFINITIONS} ) add_definitions( -DQT_SHARED ) add_definitions( -DQT_SHAREDPOINTER_TRACK_POINTERS ) diff --git a/src/libcalamares/partitionmanager b/src/libcalamares/partitionmanager new file mode 160000 index 000000000..11a8f4f14 --- /dev/null +++ b/src/libcalamares/partitionmanager @@ -0,0 +1 @@ +Subproject commit 11a8f4f14553ed0270dcd3b9acdca3b5b9c5bb43 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..8ef83d6e9 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(calapmtest calapmtest.cpp) +add_definitions(-DCALAMARES) +target_link_libraries(calapmtest calapm Qt5::Core) diff --git a/tests/calapmtest.cpp b/tests/calapmtest.cpp new file mode 100644 index 000000000..a1d07a291 --- /dev/null +++ b/tests/calapmtest.cpp @@ -0,0 +1,214 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +using namespace std; + +static const char* SCRATCH_DEVICE_NAME = "/dev/sdb"; + +static ostream& operator<<( ostream& out, const QString& s ) +{ + return out << qPrintable( s ); +} + +void dumpChildren( const PartitionNode* parent, int depth ) +{ + QString prefix( depth, ' ' ); + for ( const auto& partition : parent->children() ) + { + cout << prefix + "- " + partition->partitionPath() << endl; + cout << prefix + " fs: " + partition->fileSystem().name() << endl; + cout << prefix + " mount point: " + partition->mountPoint() << endl; + dumpChildren( partition, depth + 2 ); + } +} + +void showInfo( CoreBackend* backend ) +{ + QList devices = backend->scanDevices(); + cout << devices.count() << " device(s)\n"; + for ( auto device : devices ) + { + cout << "\n# Device: " << device->name() << endl; + cout << "node: " << device->deviceNode() << endl; + cout << "capacity: " << ( device->capacity() / 1024 / 1024 / 1024 ) << endl; + + PartitionNode* parent = device->partitionTable(); + dumpChildren( parent, 0 ); + } + qDeleteAll( devices ); +} + +void wipe( CoreBackend* backend ) +{ + Report report( 0 ); + + QScopedPointer device( backend->scanDevice( SCRATCH_DEVICE_NAME ) ); + Q_ASSERT( device.data() ); + + QScopedPointer backendDevice( backend->openDevice( device->deviceNode() ) ); + Q_ASSERT( backendDevice.data() ); + + PartitionTable* table = device->partitionTable(); + Q_ASSERT( table ); + bool ok = backendDevice->createPartitionTable( report, *table ); + if ( !ok ) + { + cerr << "Failed to recreate partition table\n"; + } + cerr << report.toText() << endl; +} + +bool createPartition( CoreBackend* backend, Report* report, Device* device, PartitionNode* parent, FileSystem* fs, PartitionTable::Flags flags = PartitionTable::FlagNone ) +{ + QScopedPointer backendDevice( backend->openDevice( device->deviceNode() ) ); + Q_ASSERT( backendDevice.data() ); + + QScopedPointer partition( new Partition( parent, *device, PartitionRole( PartitionRole::Primary ), + fs, fs->firstSector(), fs->lastSector(), QString() /* path */ + ) ); + + QScopedPointer backendPartitionTable( backendDevice->openPartitionTable() ); + Q_ASSERT( backendPartitionTable ); + + cout << "Creating partition\n"; + QString partitionPath = backendPartitionTable->createPartition( *report, *partition ); + if ( partitionPath.isEmpty() ) + { + cerr << "Failed to create partition\n"; + return false; + } + cout << "Partition created at " << partitionPath << endl; + backendPartitionTable->commit(); + + // Create filesystem + cout << "Creating filesystem\n"; + if ( !fs->create( *report, partitionPath ) ) + { + cerr << "Failed to create filesystem\n"; + return false; + } + + cout << "Updating partition table\n"; + if ( !backendPartitionTable->setPartitionSystemType( *report, *partition ) ) + { + cerr << "Failed to update partition table\n"; + return false; + } + + if ( flags != PartitionTable::FlagNone ) + { + QScopedPointer backendPartition( backendPartitionTable->getPartitionBySector( partition->firstSector() ) ); + Q_ASSERT( backendPartition ); + for ( auto flag : PartitionTable::flagList() ) + { + if ( !backendPartition->setFlag( *report, flag, true ) ) + { + cerr << "Failed to set flag " << flag << endl; + return false; + } + } + } + + backendPartitionTable->commit(); + return true; +} + +void createPartitions( CoreBackend* backend ) +{ + Report report( 0 ); + + QScopedPointer device( backend->scanDevice( SCRATCH_DEVICE_NAME ) ); + Q_ASSERT( device.data() ); + + PartitionTable* table = device->partitionTable(); + Q_ASSERT( table ); + + const int SWAP_SIZE = 200 * 1024 * 1024; + + qint64 rootStart = table->firstUsable(); + qint64 rootEnd = table->lastUsable() - SWAP_SIZE / device->logicalSectorSize(); + cout << "sectors for /: " << rootStart << " - " << rootEnd << endl; + FileSystem* fs = new FS::ext4::ext4( rootStart, rootEnd, 0, "Calamares" ); + + if ( !createPartition( backend, &report, device.data(), table, fs, PartitionTable::FlagBoot ) ) + { + cerr << report.toText() << endl; + return; + } + + qint64 swapStart = rootEnd + 1; + qint64 swapEnd = table->lastUsable(); + cout << "sectors for swap: " << swapStart << " - " << swapEnd << endl; + fs = new FS::linuxswap::linuxswap( swapStart, swapEnd, 0, "swap" ); + if ( !createPartition( backend, &report, device.data(), table, fs ) ) + { + cerr << report.toText() << endl; + return; + } +} + +int main( int argc, char** argv ) +{ + QCoreApplication app( argc, argv ); + + if ( !CalaPM::init() ) + { + return 1; + } + CoreBackend* backend = CoreBackendManager::self()->backend(); + Q_ASSERT( backend ); + + QString cmd( argv[1] ); + if ( cmd == "info" ) + { + showInfo( backend ); + } + else if ( cmd == "wipe" ) + { + wipe( backend ); + } + else if ( cmd == "partitions" ) + { + createPartitions( backend ); + } + else + { + cerr << "Unknown command " << cmd << endl; + return 1; + } + return 0; +}