gparted/include/Partition.h

198 lines
7.7 KiB
C
Raw Normal View History

/* Copyright (C) 2004 Bart
* Copyright (C) 2008, 2009, 2010 Curtis Gedak
2004-09-19 14:24:53 -06:00
*
* 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.
2004-09-19 14:24:53 -06:00
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
2004-09-19 14:24:53 -06:00
*/
/* READ THIS!!
2004-10-02 13:30:20 -06:00
* Partition isn't really a partition. It's more like a geometry, a continuous part of the disk.
* I use it to represent partitions as well as unallocated spaces
2004-09-19 14:24:53 -06:00
*/
#ifndef GPARTED_PARTITION_H
#define GPARTED_PARTITION_H
2004-09-19 14:24:53 -06:00
#include "Utils.h"
#include "PartitionVector.h"
2004-09-20 09:46:21 -06:00
#include <glibmm/ustring.h>
2004-09-19 14:24:53 -06:00
namespace GParted
{
2004-09-19 14:24:53 -06:00
enum PartitionType {
TYPE_PRIMARY = 0, // Primary partition on a partitioned drive
TYPE_LOGICAL = 1, // Logical partition on a partitioned drive
TYPE_EXTENDED = 2, // Extended partition on a partitioned drive
TYPE_UNALLOCATED = 3, // Unallocated space on a partitioned drive
TYPE_UNPARTITIONED = 4 // Unpartitioned whole drive
2004-09-19 14:24:53 -06:00
};
2004-09-25 08:12:07 -06:00
enum PartitionStatus {
STAT_REAL = 0,
STAT_NEW = 1,
STAT_COPY = 2,
STAT_FORMATTED = 3
2004-09-25 08:12:07 -06:00
};
enum PartitionAlignment {
ALIGN_CYLINDER = 0, //Align to nearest cylinder
ALIGN_MEBIBYTE = 1, //Align to nearest mebibyte
ALIGN_STRICT = 2 //Strict alignment - no rounding
// Indicator if start and end sectors must remain unchanged
};
class Partition; // Forward declarations as Partition and PartitionVector are
class PartitionVector; // mutually recursive classes.
// References:
// * Mutually recursive classes
// http://stackoverflow.com/questions/3410637/mutually-recursive-classes
// * recursive definition in CPP
// http://stackoverflow.com/questions/4300420/recursive-definition-in-cpp
2004-09-19 14:24:53 -06:00
class Partition
{
public:
Partition() ;
virtual ~Partition();
virtual Partition * clone() const;
void Reset() ;
2004-09-19 14:24:53 -06:00
//simple Set-functions. only for convenience, since most members are public
void Set( const Glib::ustring & device_path,
const Glib::ustring & partition,
int partition_number,
PartitionType type,
FSType fstype,
Sector sector_start,
Sector sector_end,
Byte_Value sector_size,
bool inside_extended,
bool busy );
2004-09-19 14:24:53 -06:00
Record unallocated space within a partition (#499202) Currently GParted assumes that a file system fills its containing partition. This is not always true and can occur when resizing is performed outside of GParted or a resize operation fails. GParted doesn't display any information about unallocated space to the user and in most cases it is simply included in used space. Add partition unallocated space accounting. Make GParted record the unallocated space for mounted file system and display a warning in the Partition Information dialog when too much unallocated space is found. Partition::set_sector_usage( fs_size, fs_unused ), is the new preferred method of recording file system usage because it allows the unallocated space in a partition to be calculated. Partition::Set_Unused() and Partition::set_used() are now deprecated. NOTES: 1) Set the minimum unallocated space to be 5% before considering it significant to avoid false reporting. Worst case found was a mounted xfs file system in a 100MiB partition, which reports as ~4.7% unallocated according to file system size from statvfs(). However, it reports as having no unallocated space using xfs specific tools. 2) Unallocated space is only a graphical representation for the user. GParted must still use relevant tools to resize file systems before shrinking the data and can't assume all unallocated space exists after the file system at the end of the partition. Bug #499202 - gparted does not see the difference if partition size differs from filesystem size
2012-01-10 07:13:41 -07:00
void set_sector_usage( Sector sectors_fs_size, Sector sectors_fs_unused ) ;
virtual bool sector_usage_known() const;
virtual Sector estimated_min_size() const;
virtual Sector get_sectors_used() const;
virtual Sector get_sectors_unused() const;
virtual Sector get_sectors_unallocated() const;
void get_usage_triple( int imax, int & i1, int & i2, int & i3 ) const ;
virtual void resize( const Partition & new_size );
void Set_Unallocated( const Glib::ustring & device_path,
Sector sector_start,
Sector sector_end,
Byte_Value sector_size,
bool inside_extended );
Add and use Partition::set_unpartitioned() method (#788308) PATCHSET OVERVIEW: When unpartitioned drive read-write support was added this commit added a whole_device flag: 5098744f9aa958ba18d2a4657ea4345e275c885b Add whole_device flag to the partition object (#743181) Using a whole_device flags now seems not the correct way to model unpartitioned drives. GParted models an uninitialised drive as: .path = _("uninitialized") .type = TYPE_UNALLOCATED .whole_device = true .filesystem = FS_UNALLOCATED and a whole drive file system, using ext4 for example, as: .path = "/dev/sdb" .type = TYPE_PRIMARY .whole_device = true .filesystem = FS_EXT4 No partitioning changed yet the type of the partition in the model changed between TYPE_UNALLOCATED and TYPE_PRIMARY depending on whether the whole drive contains a recognised file system or not. The partition object describing a file system within a LUKS encryption mapping is another case of the model not matching reality. .path = /dev/mapper/crypt_sdb1_crypt .type = TYPE_PRIMARY .whole_device = true .filesystem = FS_EXT4 There is no partition table within the encryption mapping, the file system fills it, but GParted records it as a primary partition. Make TYPE_UNALLOCATED and TYPE_PRIMARY be reserved for representing unallocated space and primary partitions within a partitioned disk drive and introduce new TYPE_UNPARTITIONED for all cases of an unpartitioned whole disk drive. The GParted UI does differentiate between an unallocated whole disk device and anything else by requiring a partition table to be created first, even if that is just the loop partition table. That determination can simply look for the partition object containing file system type FS_UNALLOCATED instead. THIS PATCH: Create set_unpartitioned() helper method to set a partition object to represent a whole disk drive and use everywhere such an object is modelled. This matches what existing methods Set_Unallocated() and indeed Set() do for unallocated space and any type of partition respectively. For now the partition type is still set to either TYPE_UNALLOCATED or TYPE_PRIMARY so the rest of the code base remains the same. TYPE_UNPARTITIONED will be introduced later. Bug 788308 - Remove whole_device partition flag
2016-08-13 06:28:58 -06:00
void set_unpartitioned( const Glib::ustring & device_path,
const Glib::ustring & partition_path,
FSType fstype,
Add and use Partition::set_unpartitioned() method (#788308) PATCHSET OVERVIEW: When unpartitioned drive read-write support was added this commit added a whole_device flag: 5098744f9aa958ba18d2a4657ea4345e275c885b Add whole_device flag to the partition object (#743181) Using a whole_device flags now seems not the correct way to model unpartitioned drives. GParted models an uninitialised drive as: .path = _("uninitialized") .type = TYPE_UNALLOCATED .whole_device = true .filesystem = FS_UNALLOCATED and a whole drive file system, using ext4 for example, as: .path = "/dev/sdb" .type = TYPE_PRIMARY .whole_device = true .filesystem = FS_EXT4 No partitioning changed yet the type of the partition in the model changed between TYPE_UNALLOCATED and TYPE_PRIMARY depending on whether the whole drive contains a recognised file system or not. The partition object describing a file system within a LUKS encryption mapping is another case of the model not matching reality. .path = /dev/mapper/crypt_sdb1_crypt .type = TYPE_PRIMARY .whole_device = true .filesystem = FS_EXT4 There is no partition table within the encryption mapping, the file system fills it, but GParted records it as a primary partition. Make TYPE_UNALLOCATED and TYPE_PRIMARY be reserved for representing unallocated space and primary partitions within a partitioned disk drive and introduce new TYPE_UNPARTITIONED for all cases of an unpartitioned whole disk drive. The GParted UI does differentiate between an unallocated whole disk device and anything else by requiring a partition table to be created first, even if that is just the loop partition table. That determination can simply look for the partition object containing file system type FS_UNALLOCATED instead. THIS PATCH: Create set_unpartitioned() helper method to set a partition object to represent a whole disk drive and use everywhere such an object is modelled. This matches what existing methods Set_Unallocated() and indeed Set() do for unallocated space and any type of partition respectively. For now the partition type is still set to either TYPE_UNALLOCATED or TYPE_PRIMARY so the rest of the code base remains the same. TYPE_UNPARTITIONED will be introduced later. Bug 788308 - Remove whole_device partition flag
2016-08-13 06:28:58 -06:00
Sector length,
Byte_Value sector_size,
bool busy );
2004-09-19 14:24:53 -06:00
//update partition number (used when a logical partition is deleted)
void Update_Number( int new_number );
void set_path( const Glib::ustring & path );
2010-04-27 11:28:36 -06:00
Byte_Value get_byte_length() const ;
Sector get_sector_length() const ;
Glib::ustring get_path() const ;
void add_mountpoint( const Glib::ustring & mountpoint );
void add_mountpoints( const std::vector<Glib::ustring> & mountpoints );
Glib::ustring get_mountpoint() const ;
void clear_mountpoints() ;
std::vector<Glib::ustring> get_mountpoints() const ;
Sector get_sector() const ;
bool test_overlap( const Partition & partition ) const ;
bool filesystem_label_known() const;
Glib::ustring get_filesystem_label() const;
void set_filesystem_label( const Glib::ustring & filesystem_label );
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
// Message accessors. Messages are stored locally and accessed globally.
// Stored locally means the messages are stored in the Partition object to which
// they are added so push_back_messages() and append_messages() are non-virtual.
// Accessed globally means that in the case of derived objects which are composed
// of more that one Partition object, i.e. PartitionLUKS, the messages have to be
// accessible from all copies within the derived object hierarchy. Hence
// have_messages(), get_messages() and clear_messages() are virtual to allow for
// overridden implementations.
virtual bool have_messages() const { return ! messages.empty(); };
virtual std::vector<Glib::ustring> get_messages() const { return messages; };
virtual void clear_messages() { messages.clear(); };
void push_back_message(const Glib::ustring& msg) { messages.push_back(msg); };
void append_messages(const std::vector<Glib::ustring>& msgs)
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
{ messages.insert( messages.end(), msgs.begin(), msgs.end() ); }
// Interface to return reference to the Partition object directly containing the
// file system. Will be overridden in derived PartitionLUKS.
virtual const Partition & get_filesystem_partition() const { return *this; };
virtual Partition & get_filesystem_partition() { return *this; };
virtual const Glib::ustring get_filesystem_string() const
{ return Utils::get_filesystem_string(fstype); };
bool operator==( const Partition & partition ) const ;
bool operator!=( const Partition & partition ) const ;
static const Glib::ustring get_partition_type_string(PartitionType type);
2004-09-19 14:24:53 -06:00
//some public members
Glib::ustring device_path ;
2004-09-19 14:24:53 -06:00
int partition_number;
PartitionType type;// UNALLOCATED, PRIMARY, LOGICAL, etc...
2004-09-25 08:12:07 -06:00
PartitionStatus status; //STAT_REAL, STAT_NEW, etc..
PartitionAlignment alignment; //ALIGN_CYLINDER, ALIGN_STRICT, etc
FSType fstype;
Glib::ustring uuid ;
Glib::ustring name;
2004-09-19 14:24:53 -06:00
Sector sector_start;
Sector sector_end;
Sector sectors_used;
Sector sectors_unused;
Record unallocated space within a partition (#499202) Currently GParted assumes that a file system fills its containing partition. This is not always true and can occur when resizing is performed outside of GParted or a resize operation fails. GParted doesn't display any information about unallocated space to the user and in most cases it is simply included in used space. Add partition unallocated space accounting. Make GParted record the unallocated space for mounted file system and display a warning in the Partition Information dialog when too much unallocated space is found. Partition::set_sector_usage( fs_size, fs_unused ), is the new preferred method of recording file system usage because it allows the unallocated space in a partition to be calculated. Partition::Set_Unused() and Partition::set_used() are now deprecated. NOTES: 1) Set the minimum unallocated space to be 5% before considering it significant to avoid false reporting. Worst case found was a mounted xfs file system in a 100MiB partition, which reports as ~4.7% unallocated according to file system size from statvfs(). However, it reports as having no unallocated space using xfs specific tools. 2) Unallocated space is only a graphical representation for the user. GParted must still use relevant tools to resize file systems before shrinking the data and can't assume all unallocated space exists after the file system at the end of the partition. Bug #499202 - gparted does not see the difference if partition size differs from filesystem size
2012-01-10 07:13:41 -07:00
Sector sectors_unallocated; //Difference between the size of the partition and the file system
Sector significant_threshold; //Threshold from intrinsic to significant unallocated sectors
bool inside_extended;
2004-09-19 14:24:53 -06:00
bool busy;
bool fs_readonly; // Is the file system mounted read-only?
std::vector<Glib::ustring> flags ;
PartitionVector logicals;
bool strict_start ; //Indicator if start sector must stay unchanged
Sector free_space_before ; //Free space preceding partition value
Byte_Value sector_size ; //Sector size of the disk device needed for converting to/from sectors and bytes.
Byte_Value fs_block_size; // Block size of of the file system, or -1 when unknown.
2004-09-19 14:24:53 -06:00
private:
Partition & operator=( Partition & rhs ); // Not implemented copy assignment operator
static void get_usage_triple_helper( Sector stot, Sector s1, Sector s2, Sector s3, int imax, int & i1, int & i2, int & i3 ) ;
Fix minor unallocated space display issue in the Info dialog (#499202) For specific partition usage values the right hand border of the partition graphic in the Information dialog would be displayed as grey rather than the color assigned to the partition. Steps to reproduce fault: Create 1024 MiB partition # lvm pvcreate /dev/sda12 # lvm vgcreate GParted-VG1 /dev/sda12 View partition information Fragment from Dialog_Partition_Info::init_drawingarea(): 139 else if ( partition .sector_usage_known() ) 140 { 141 used = Utils::round( ( 400 - BORDER *2 ) / ( dlength / partition .get_sectors_used() ) ) ; 142 unused = Utils::round( ( 400 - BORDER *2 ) / ( dlength / partition .get_sectors_unused() ) ) ; 143 unallocated = 400 - BORDER *2 - used - unused ; 144 } For this issue the above values are both exactly x.5 and both round upwards, resulting in unallocated being -1. used = round((400 - 8*2)/(2097152.0/8192)) = round(1.5) unused = round((400 - 8*2)/(2097152.0/2088960)) = round(382.5) unallocated = 400 - 8*2 - 2 - 383 = -1 The simple fix would be to use floor() instead of round() in the calculation of either used or unused. The same fix would also need to be applied in Display_Info() for the calculation of the percentage figures. Unfortunately this simple fix can lead to odd figures when the used or unused is close to zero and floor() or ceil() is effectively applied rather than round(). For example: Size: 227.23 GiB Used: 28.00 KiB ( 1% ) Unused: 180.00 GiB ( 79% ) Unallocated: 47.23 GiB ( 20% ) Used figure of 28 KiB in 227 GiB partition should be rounded to 0% but wasn't. Write Partition::calc_usage_triple() which calculates the "best" figures by rounding the smaller two figures and subtracts them from the desired total for the largest figure. Apply to the calculation of the partition usage percentage figures in the Information dialog and the partition usage graphic in the same dialog and the main window. Bug #499202 - gparted does not see the difference if partition size differs from filesystem size
2012-06-20 16:53:05 -06:00
Sector calc_significant_unallocated_sectors() const ;
2004-09-19 14:24:53 -06:00
Glib::ustring path;
std::vector<Glib::ustring> mountpoints ;
bool have_filesystem_label;
Glib::ustring filesystem_label;
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
std::vector<Glib::ustring> messages;
2004-09-19 14:24:53 -06:00
};
}//GParted
#endif /* GPARTED_PARTITION_H */