gparted/src/PartitionLUKS.cc

255 lines
8.6 KiB
C++

/* Copyright (C) 2015 Mike Fleetwood
*
* 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 2 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 "Partition.h"
#include "PartitionLUKS.h"
#include "Utils.h"
namespace GParted
{
PartitionLUKS::PartitionLUKS() : header_size( 0 )
{
// Nothing further to do here as the base class Partition default constructor,
// which calls Partition::Reset(), is called for this object and also to
// initialise the encrypted member variable of type Partition.
}
PartitionLUKS::~PartitionLUKS()
{
}
PartitionLUKS * PartitionLUKS::clone() const
{
// Virtual copy constructor method
return new PartitionLUKS( *this );
}
// Specialist clone creating a plain Partition object from a PartitionLUKS object.
// Created partition is as though the file system wasn't encrypted, but adds the LUKS
// overhead into the file system usage.
Partition * PartitionLUKS::clone_as_plain() const
{
// Clone the partition.
// WARNING:
// Deliberate object slicing of *this from PartitionLUKS to Partition.
Partition * plain_ptn = new Partition( *this );
// Copy over file system attributes.
plain_ptn->fstype = this->encrypted.fstype;
plain_ptn->uuid = this->encrypted.uuid;
plain_ptn->busy = this->encrypted.busy;
plain_ptn->fs_block_size = this->encrypted.fs_block_size;
Sector fs_size = this->header_size + this->encrypted.sectors_used + this->encrypted.sectors_unused;
plain_ptn->set_sector_usage( fs_size, this->encrypted.sectors_unused );
plain_ptn->clear_mountpoints();
plain_ptn->add_mountpoints( this->encrypted.get_mountpoints() );
if ( this->encrypted.filesystem_label_known() )
plain_ptn->set_filesystem_label( this->encrypted.get_filesystem_label() );
plain_ptn->clear_messages();
plain_ptn->append_messages( this->encrypted.get_messages() );
return plain_ptn;
}
// Mostly a convenience method calling Partition::set_unpartitioned() on the encrypted
// Partition but also sets private header_size. Makes encrypted Partition object look
// like a whole disk device as /dev/mapper/CRYPTNAME contains no partition table and the
// file system starts from sector 0 going to the very end.
void PartitionLUKS::set_luks( const Glib::ustring & path,
FSType fstype,
Sector header_size,
Sector mapping_size,
Byte_Value sector_size,
bool busy )
{
encrypted.set_unpartitioned( path,
path,
fstype,
mapping_size,
sector_size,
busy );
this->header_size = header_size;
}
bool PartitionLUKS::sector_usage_known() const
{
if ( busy )
// For an open dm-crypt mapping the usage of both the LUKS and encrypted
// file system must be known.
return Partition::sector_usage_known() && encrypted.sector_usage_known();
return Partition::sector_usage_known();
}
// An encrypted partition is laid out, and usage figures calculated like this:
//
// Partition
// |<---------------------------------------->| <- this PartitionLUKS object
// LUKS LUKS
// Header Mapping
// |<--->||<----------------------->| <- encrypted Partition object member
// hhhhhhh <- this->header_size
// 1111111111111111111111111111111111uuuuuuuuuu <- this->sectors_{used,unused,unallocated}
// Encrypted file system
// |<----------------->|
// 111111111111110000000uuuuuu <- encrypted.sectors_{used,unused,unallocated}
// encrypted.sector_start = 0
// encrypted.sector_end = (last sector in LUKS mapping)
//
// 1111111111111111111110000000uuuuuuuuuuuuuuuu <- Overall usage figures as used in the following
// usage related methods.
// Legend:
// 1 - used sectors
// 0 - unused sectors
// u - unallocated sectors
// h - LUKS header sectors
//
// Calculations:
// total_used = LUKS Header size + Encrypted file system used
// = this->header_size + encrypted.sectors_used
// total_unallocated = LUKS unallocated + Encrypted file system unallocated
// = this->sectors_unallocated + encrypted.sectors_unallocated
// total_unused = LUKS unused + Encrypted file system unused
// = 0 + encrypted.sectors_unused
//
// By definition LUKS unused is 0 (See luks::set_used_sectors()).
// Return estimated minimum size to which the partition can be resized.
// See Partition::estimated_min_size() for unallocated threshold reasoning.
Sector PartitionLUKS::estimated_min_size() const
{
if ( busy )
{
// For an open dm-crypt mapping work with above described totals.
if ( sectors_used >= 0 && encrypted.sectors_used >= 0 )
{
Sector total_used = header_size + encrypted.sectors_used;
Sector total_unallocated = sectors_unallocated + encrypted.sectors_unallocated;
return total_used + std::min( total_unallocated, significant_threshold );
}
return -1;
}
return Partition::estimated_min_size();
}
// Return user displayable used sectors.
// See Partition::get_sectors_used() for unallocated threshold reasoning.
Sector PartitionLUKS::get_sectors_used() const
{
if ( busy )
{
// For an open dm-crypt mapping work with above described totals.
if ( sectors_used >= 0 && encrypted.sectors_used >= 0 )
{
Sector total_used = header_size + encrypted.sectors_used;
Sector total_unallocated = sectors_unallocated + encrypted.sectors_unallocated;
if ( total_unallocated < significant_threshold )
return total_used + total_unallocated;
else
return total_used;
}
return -1;
}
return Partition::get_sectors_used();
}
// Return user displayable unused sectors.
// See above described totals.
Sector PartitionLUKS::get_sectors_unused() const
{
if ( busy )
return encrypted.get_sectors_unused();
return Partition::get_sectors_unused();
}
// Return user displayable unallocated sectors.
// See Partition::get_sectors_unallocated() for unallocated threshold reasoning.
Sector PartitionLUKS::get_sectors_unallocated() const
{
if ( busy )
{
// For an open dm-crypt mapping work with above described totals.
Sector total_unallocated = sectors_unallocated + encrypted.sectors_unallocated;
if ( total_unallocated < significant_threshold )
return 0;
else
return total_unallocated;
}
return Partition::get_sectors_unallocated();
}
// Update size, position and FS usage from new_size.
void PartitionLUKS::resize( const Partition & new_size )
{
Partition::resize( new_size );
// As per discussion in luks::set_used_sectors() LUKS itself is always 100% used.
set_sector_usage( get_sector_length(), 0LL );
Sector mapping_size = get_sector_length() - header_size;
encrypted.sector_end = mapping_size - 1LL;
Sector fs_unused = mapping_size - encrypted.sectors_used;
encrypted.set_sector_usage( mapping_size, fs_unused );
}
bool PartitionLUKS::have_messages() const
{
if ( busy )
return Partition::have_messages() || encrypted.have_messages();
return Partition::have_messages();
}
std::vector<Glib::ustring> PartitionLUKS::get_messages() const
{
if ( busy )
{
std::vector<Glib::ustring> msgs = Partition::get_messages();
std::vector<Glib::ustring> msgs2 = encrypted.get_messages();
msgs.insert( msgs.end(), msgs2.begin(), msgs2.end() );
return msgs;
}
return Partition::get_messages();
}
void PartitionLUKS::clear_messages()
{
Partition::clear_messages();
encrypted.clear_messages();
}
const Partition & PartitionLUKS::get_filesystem_partition() const
{
if ( busy )
return encrypted;
return *this;
}
Partition & PartitionLUKS::get_filesystem_partition()
{
if ( busy )
return encrypted;
return *this;
}
const Glib::ustring PartitionLUKS::get_filesystem_string() const
{
if ( busy )
return Utils::get_filesystem_string(true, encrypted.fstype);
return Utils::get_encrypted_string();
}
} //GParted