255 lines
8.6 KiB
C++
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
|