gparted/include/GParted_Core.h

215 lines
9.7 KiB
C
Raw Normal View History

/* Copyright (C) 2004 Bart
* Copyright (C) 2008, 2009, 2010, 2011, 2012 Curtis Gedak
*
* 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/>.
*/
#ifndef GPARTED_GPARTED_CORE_H
#define GPARTED_GPARTED_CORE_H
#include "../include/FileSystem.h"
#include "../include/Operation.h"
#include <parted/parted.h>
#include <vector>
#include <fstream>
namespace GParted
{
class GParted_Core
{
public:
static Glib::Thread *mainthread;
GParted_Core() ;
~GParted_Core() ;
void init_filesystems() ;
void find_supported_filesystems() ;
void set_user_devices( const std::vector<Glib::ustring> & user_devices ) ;
void set_devices( std::vector<Device> & devices ) ;
void set_devices_thread( std::vector<Device> * pdevices );
void guess_partition_table(const Device & device, Glib::ustring &buff);
bool snap_to_cylinder( const Device & device, Partition & partition, Glib::ustring & error ) ;
bool snap_to_mebibyte( const Device & device, Partition & partition, Glib::ustring & error ) ;
bool snap_to_alignment( const Device & device, Partition & partition, Glib::ustring & error ) ;
bool apply_operation_to_disk( Operation * operation );
bool set_disklabel( const Device & device, const Glib::ustring & disklabel );
bool new_disklabel( const Glib::ustring & device_path, const Glib::ustring & disklabel );
bool toggle_flag( const Partition & partition, const Glib::ustring & flag, bool state ) ;
const std::vector<FS> & get_filesystems() const ;
const FS & get_fs( GParted::FILESYSTEM filesystem ) const ;
static std::vector<Glib::ustring> get_disklabeltypes() ;
static bool is_dev_mounted( const Glib::ustring & path ) ;
static std::vector<Glib::ustring> get_all_mountpoints() ;
std::map<Glib::ustring, bool> get_available_flags( const Partition & partition ) ;
Glib::ustring get_libparted_version() ;
Glib::ustring get_thread_status_message() ;
static FileSystem * get_filesystem_object( FILESYSTEM filesystem );
static bool supported_filesystem( FILESYSTEM fstype );
static bool filesystem_resize_disallowed( const Partition & partition ) ;
private:
//detectionstuff..
static void init_maps() ;
void set_thread_status_message( Glib::ustring msg ) ;
static void read_mountpoints_from_file( const Glib::ustring & filename,
Fallback to reading mount command output instead of /etc/mtab (#723842) With linux 3.5 and later, the device used to mount a btrfs file system is updated in /proc/mounts when the previous mounting device is removed from the file system. Most recent distributions make /etc/mtab a symbolic link to /proc/mounts. However some still have /etc/mtab as a plain file only updated by mount and umount, thus showing the old device name which is no longer part of the file system. On Ubuntu 13.10, which has /etc/mtab as a plain file managed by mount and umount: # mkfs.btrfs /dev/sdb1 # mount /dev/sdb1 /mnt/1 # btrfs device add /dev/sdb2 /mnt/1 # btrfs device delete /dev/sdb1 /mnt/1 # sync # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: e47775a6-e5ad-4fb4-9ea4-1570aa5b4009 Total devices 2 FS bytes used 28.00KB devid 2 size 2.00GB used 272.00MB path /dev/sdb2 # fgrep btrfs /proc/mounts /dev/sdb2 /mnt/1 btrfs rw,relatime,space_cache 0 0 # ls -l /etc/mtab -rw-r--r-- 1 root root 842 Apr 15 19:41 /etc/mtab # fgrep btrfs /etc/mtab /dev/sdb1 /mnt/1 btrfs rw 0 0 This causes GParted to report /dev/sdb1 as busy and mounted at /mnt/1 when it is no longer mounted. This effects recent releases of Ubuntu, 13.04, 13.10 and 14.04. Either /etc/mtab is a symlink and is identical to /proc/mounts or /etc/mtab is a plain file with wrong information. Fix by not reading mounted file systems from /etc/mtab. However old distributions only contain 'rootfs' and '/dev/root' device names for the / (root) file system with '/dev/root' being a block device rather than a symlink to the true device. For example from CentOS 5.x: # fgrep ' / ' /proc/mounts rootfs / rootfs rw 0 0 /dev/root / ext3 rw,data=ordered 0 0 # ls -l /dev/root brw------- 1 root root 8, 3 Jun 4 2013 /dev/root This prevents identification, and therefore busy detection, of the device containing the / (root) file system. Used to read /etc/mtab to get the root file system device name. # fgrep ' / ' /etc/mtab /dev/sda3 / ext3 rw 0 0 # ls -l /dev/sda3 brw-r----- 1 root disk 8, 3 Jun 4 2013 /dev/sda3 As per commit: 409096f739118af95e3bff4484fdedb7885c97a2 improved scanning for root mountpoint (/) ... but, as discussed above, this contains an out of date device name after the mounting device has been dynamically removed from a multi-device btrfs, thus identifying the wrong device as busy. Instead fall back to reading mounted file systems from the output of the mount command, but only when required. # mount | fgrep ' / ' /dev/sda3 on / type ext3 (rw) Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-04-14 08:21:55 -06:00
std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) ;
static void add_node_and_mountpoint( std::map< Glib::ustring, std::vector<Glib::ustring> > & map,
Glib::ustring & node,
Glib::ustring & mountpoint ) ;
static void read_mountpoints_from_file_swaps( const Glib::ustring & filename,
Fallback to reading mount command output instead of /etc/mtab (#723842) With linux 3.5 and later, the device used to mount a btrfs file system is updated in /proc/mounts when the previous mounting device is removed from the file system. Most recent distributions make /etc/mtab a symbolic link to /proc/mounts. However some still have /etc/mtab as a plain file only updated by mount and umount, thus showing the old device name which is no longer part of the file system. On Ubuntu 13.10, which has /etc/mtab as a plain file managed by mount and umount: # mkfs.btrfs /dev/sdb1 # mount /dev/sdb1 /mnt/1 # btrfs device add /dev/sdb2 /mnt/1 # btrfs device delete /dev/sdb1 /mnt/1 # sync # btrfs filesystem show /dev/sdb1 # btrfs filesystem show /dev/sdb2 Label: none uuid: e47775a6-e5ad-4fb4-9ea4-1570aa5b4009 Total devices 2 FS bytes used 28.00KB devid 2 size 2.00GB used 272.00MB path /dev/sdb2 # fgrep btrfs /proc/mounts /dev/sdb2 /mnt/1 btrfs rw,relatime,space_cache 0 0 # ls -l /etc/mtab -rw-r--r-- 1 root root 842 Apr 15 19:41 /etc/mtab # fgrep btrfs /etc/mtab /dev/sdb1 /mnt/1 btrfs rw 0 0 This causes GParted to report /dev/sdb1 as busy and mounted at /mnt/1 when it is no longer mounted. This effects recent releases of Ubuntu, 13.04, 13.10 and 14.04. Either /etc/mtab is a symlink and is identical to /proc/mounts or /etc/mtab is a plain file with wrong information. Fix by not reading mounted file systems from /etc/mtab. However old distributions only contain 'rootfs' and '/dev/root' device names for the / (root) file system with '/dev/root' being a block device rather than a symlink to the true device. For example from CentOS 5.x: # fgrep ' / ' /proc/mounts rootfs / rootfs rw 0 0 /dev/root / ext3 rw,data=ordered 0 0 # ls -l /dev/root brw------- 1 root root 8, 3 Jun 4 2013 /dev/root This prevents identification, and therefore busy detection, of the device containing the / (root) file system. Used to read /etc/mtab to get the root file system device name. # fgrep ' / ' /etc/mtab /dev/sda3 / ext3 rw 0 0 # ls -l /dev/sda3 brw-r----- 1 root disk 8, 3 Jun 4 2013 /dev/sda3 As per commit: 409096f739118af95e3bff4484fdedb7885c97a2 improved scanning for root mountpoint (/) ... but, as discussed above, this contains an out of date device name after the mounting device has been dynamically removed from a multi-device btrfs, thus identifying the wrong device as busy. Instead fall back to reading mounted file systems from the output of the mount command, but only when required. # mount | fgrep ' / ' /dev/sda3 on / type ext3 (rw) Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-04-14 08:21:55 -06:00
std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) ;
static bool have_rootfs_dev( std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) ;
static void read_mountpoints_from_mount_command( std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) ;
Glib::ustring get_partition_path( PedPartition * lp_partition ) ;
void set_device_partitions( Device & device, PedDevice* lp_device, PedDisk* lp_disk ) ;
void set_device_one_partition( Device & device, PedDevice * lp_device, FILESYSTEM fstype,
std::vector<Glib::ustring> & messages );
void set_partition_label_and_uuid( Partition & partition );
static FILESYSTEM recognise_filesystem_signature( PedDevice * lp_device, PedPartition * lp_partition );
GParted::FILESYSTEM get_filesystem( PedDevice* lp_device, PedPartition* lp_partition,
std::vector<Glib::ustring>& messages ) ;
void read_label( Partition & partition ) ;
void read_uuid( Partition & partition ) ;
void insert_unallocated( const Glib::ustring & device_path,
std::vector<Partition> & partitions,
Sector start,
Sector end,
Byte_Value sector_size,
bool inside_extended ) ;
void set_mountpoints( std::vector<Partition> & partitions ) ;
bool set_mountpoints_helper( Partition & partitions, const Glib::ustring & path ) ;
bool is_busy( FILESYSTEM fstype, const Glib::ustring & path ) ;
void set_used_sectors( std::vector<Partition> & partitions, PedDisk* lp_disk ) ;
void mounted_set_used_sectors( Partition & partition ) ;
#ifdef HAVE_LIBPARTED_FS_RESIZE
void LP_set_used_sectors( Partition & partition, PedDisk* lp_disk ) ;
#endif
void set_flags( Partition & partition, PedPartition* lp_partition ) ;
//operationstuff...
bool create( const Device & device, Partition & new_partition, OperationDetail & operationdetail ) ;
bool create_partition( Partition & new_partition, OperationDetail & operationdetail, Sector min_size = 0 ) ;
bool create_filesystem( const Partition & partition, OperationDetail & operationdetail ) ;
bool format( const Partition & partition, OperationDetail & operationdetail ) ;
bool Delete( const Partition & partition, OperationDetail & operationdetail ) ;
bool remove_filesystem( const Partition & partition, OperationDetail & operationdetail ) ;
bool label_filesystem( const Partition & partition, OperationDetail & operationdetail );
bool name_partition( const Partition & partition, OperationDetail & operationdetail );
bool change_uuid( const Partition & partition, OperationDetail & operation_detail ) ;
bool resize_move( const Device & device,
const Partition & partition_old,
Partition & partition_new,
OperationDetail & operationdetail ) ;
bool move( const Device & device,
const Partition & partition_old,
const Partition & partition_new,
OperationDetail & operationdetail ) ;
bool move_filesystem( const Partition & partition_old,
const Partition & partition_new,
OperationDetail & operationdetail ) ;
#ifdef HAVE_LIBPARTED_FS_RESIZE
bool resize_move_filesystem_using_libparted( const Partition & partition_old,
const Partition & partition_new,
OperationDetail & operationdetail ) ;
#endif
bool resize( const Partition & partition_old,
const Partition & partition_new,
OperationDetail & operationdetail ) ;
bool resize_move_partition( const Partition & partition_old,
const Partition & partition_new,
OperationDetail & operationdetail ) ;
bool resize_filesystem( const Partition & partition_old,
const Partition & partition_new,
OperationDetail & operationdetail,
bool fill_partition = false ) ;
bool maximize_filesystem( const Partition & partition, OperationDetail & operationdetail ) ;
bool copy( const Partition & partition_src,
Partition & partition_dst,
Byte_Value min_size,
OperationDetail & operationdetail ) ;
bool copy_filesystem( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
bool cancel_safe );
bool copy_filesystem( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
Byte_Value & total_done,
bool cancel_safe );
bool copy_filesystem( const Glib::ustring & src_device,
const Glib::ustring & dst_device,
Sector src_start,
Sector dst_start,
Byte_Value src_sector_size,
Byte_Value dst_sector_size,
Byte_Value src_length,
OperationDetail & operationdetail,
Byte_Value & total_done,
bool cancel_safe ) ;
void rollback_transaction( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
Byte_Value total_done ) ;
bool check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail ) ;
bool set_partition_type( const Partition & partition, OperationDetail & operationdetail ) ;
bool calibrate_partition( Partition & partition, OperationDetail & operationdetail ) ;
bool calculate_exact_geom( const Partition & partition_old,
Partition & partition_new,
OperationDetail & operationdetail ) ;
Use wipefs to clear old signatures before creating new file systems (#688882) Previously the function erase_filesystem_signatures() was used to clear file system signatures when a new partition was created and when an existing partition was formatted with a file system. However this was only available with libparted <= 2.4 and then only for the file systems which libparted supports. Having multiple different file system signatures on a partition leads to misidentification of file system. For example creating a nilfs2 over the top of a fat32 file system is detected as a fat32, not nilfs2. This shows that old file system signatures must be cleared before a new file system is created. Fix by always using "wipefs -a /dev/PARTITION" command to clear all old file system signatures rather than libparted API calls. Failure from wipefs is only considered a warning so doesn't fail the file system creation. (This doesn't yet fully meet the "MUST be cleared" requirement above. Will be fully met later in this patchset). Output from the wipefs command is displayed as a new sub-step which looks like this: v Format /dev/sda7 as xfs 00:00:05 > calibrate /dev/sda14 00:00:01 v clear old file system signatures in /dev/sda7 00:00:01 [NEW] > wipefs -a /dev/sda7 [NEW] > set partition type on /dev/sda7 00:00:02 v create new xfs file system 00:00:01 > mkfs.xfs -f -L "" /dev/sda7 Also signatures are only cleared immediately before a new file system is written and not when an unformatted partition is created. This allows recovery from accidental partition deletion by re-creating the deleted partition as unformatted. Bug #688882 - Improve clearing of file system signatures
2012-12-01 05:49:29 -07:00
bool erase_filesystem_signatures( const Partition & partition, OperationDetail & operationdetail ) ;
bool update_bootsector( const Partition & partition, OperationDetail & operationdetail ) ;
//general..
Flush devices when scanning to prevent reading stale signatures (#723842) While one partition is busy, reformat another partition from the command line. Afterwards parted/libparted still detects the original file system and GParted shows errors from the file system specific tools reporting the new file system doesn't exist. Only limitation is that the new new file system must be recognised by libparted (or by GParted's fallback file system signature detection). Case #1, File system reformatting: # parted /dev/sdb print Model: ATA SAMSUNG SSD UM41 (scsi) Disk /dev/sdb: 8012MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 1049kB 2149MB 2147MB primary ext2 2 2149MB 4296MB 2147MB primary ext2 # mount | fgrep sdb /dev/sdb1 on /mnt/1 type ext2 (rw) # mkfs.xfs -f /dev/sdb2 # blkid /dev/sdb2 /dev/sdb2: UUID="c31823a2-b81b-46fa-8246-0a59695e4834" TYPE="xfs" # parted /dev/sdb print Model: ATA SAMSUNG SSD UM41 (scsi) Disk /dev/sdb: 8012MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 1049kB 2149MB 2147MB primary ext2 2 2149MB 4296MB 2147MB primary ext2 # e2label /dev/sdb2 e2label: Bad magic number in super-block while trying to open /dev/sdb2 Couldn't find valid filesystem superblock. # dumpe2fs /dev/sdb2 dumpe2fs 1.41.12 (17-May-2010) dumpe2fs: Bad magic number in super-block while trying to open /dev/sdb2 Couldn't find valid filesystem superblock. Case #2, Removing device from multi-device btrfs: # btrfs filesystem show /dev/sdb1 Label: none uuid: a05db434-efd5-4e8c-902f-05f89a88b610 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # btrfs device delete /dev/sdb2 # btrfs filesystem show /dev/sdb1 Label: none uuid: a05db434-efd5-4e8c-902f-05f89a88b610 Total devices 1 FS bytes used 92.00KB devid 1 size 2.00GB used 714.25MB path /dev/sdb1 # btrfs filesystem show /dev/sdb2 and GParted reports this error for partition /dev/sdb2: Unable to read the contents of this file system! Because of this some operations may be unavailable. The cause might be a missing software package. The following list of software packages is required for btrfs file system support: btrfs-tools. This is another case of libparted reading from the whole disk device (/dev/sdb) yet the file system tools use the partition specific block device (/dev/sdb2), and the Linux buffer cache not providing cache coherency. Previous scenario was fixed with: 797f0b8eeb61f81da1791c3cf048b5c0abf9a550 Flush device after wiping a file system (#688882) This affects libparted 2.0 to 3.1 inclusive and is fixed by: http://git.savannah.gnu.org/cgit/parted.git/commit/?id=fb99ba5ebd0dc34204fc9f1014131d5d494805bc Revert "linux-commit: do not unnecessarily open partition device nodes" Fix by calling ped_device_sync() to guarantee cache coherency for each device during scanning. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-23 15:11:13 -06:00
bool flush_device( PedDevice * lp_device ) ;
bool get_device( const Glib::ustring & device_path, PedDevice *& lp_device, bool flush = false );
bool get_disk( PedDevice *& lp_device, PedDisk *& lp_disk, bool strict = true );
bool get_device_and_disk( const Glib::ustring & device_path,
Flush devices when scanning to prevent reading stale signatures (#723842) While one partition is busy, reformat another partition from the command line. Afterwards parted/libparted still detects the original file system and GParted shows errors from the file system specific tools reporting the new file system doesn't exist. Only limitation is that the new new file system must be recognised by libparted (or by GParted's fallback file system signature detection). Case #1, File system reformatting: # parted /dev/sdb print Model: ATA SAMSUNG SSD UM41 (scsi) Disk /dev/sdb: 8012MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 1049kB 2149MB 2147MB primary ext2 2 2149MB 4296MB 2147MB primary ext2 # mount | fgrep sdb /dev/sdb1 on /mnt/1 type ext2 (rw) # mkfs.xfs -f /dev/sdb2 # blkid /dev/sdb2 /dev/sdb2: UUID="c31823a2-b81b-46fa-8246-0a59695e4834" TYPE="xfs" # parted /dev/sdb print Model: ATA SAMSUNG SSD UM41 (scsi) Disk /dev/sdb: 8012MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 1049kB 2149MB 2147MB primary ext2 2 2149MB 4296MB 2147MB primary ext2 # e2label /dev/sdb2 e2label: Bad magic number in super-block while trying to open /dev/sdb2 Couldn't find valid filesystem superblock. # dumpe2fs /dev/sdb2 dumpe2fs 1.41.12 (17-May-2010) dumpe2fs: Bad magic number in super-block while trying to open /dev/sdb2 Couldn't find valid filesystem superblock. Case #2, Removing device from multi-device btrfs: # btrfs filesystem show /dev/sdb1 Label: none uuid: a05db434-efd5-4e8c-902f-05f89a88b610 Total devices 2 FS bytes used 156.00KB devid 2 size 2.00GB used 512.00MB path /dev/sdb2 devid 1 size 2.00GB used 240.75MB path /dev/sdb1 # mount /dev/sdb1 /mnt/1 # btrfs device delete /dev/sdb2 # btrfs filesystem show /dev/sdb1 Label: none uuid: a05db434-efd5-4e8c-902f-05f89a88b610 Total devices 1 FS bytes used 92.00KB devid 1 size 2.00GB used 714.25MB path /dev/sdb1 # btrfs filesystem show /dev/sdb2 and GParted reports this error for partition /dev/sdb2: Unable to read the contents of this file system! Because of this some operations may be unavailable. The cause might be a missing software package. The following list of software packages is required for btrfs file system support: btrfs-tools. This is another case of libparted reading from the whole disk device (/dev/sdb) yet the file system tools use the partition specific block device (/dev/sdb2), and the Linux buffer cache not providing cache coherency. Previous scenario was fixed with: 797f0b8eeb61f81da1791c3cf048b5c0abf9a550 Flush device after wiping a file system (#688882) This affects libparted 2.0 to 3.1 inclusive and is fixed by: http://git.savannah.gnu.org/cgit/parted.git/commit/?id=fb99ba5ebd0dc34204fc9f1014131d5d494805bc Revert "linux-commit: do not unnecessarily open partition device nodes" Fix by calling ped_device_sync() to guarantee cache coherency for each device during scanning. Bug #723842 - GParted resizes the wrong filesystem (does not pass the devid to btrfs filesystem resize)
2014-03-23 15:11:13 -06:00
PedDevice*& lp_device, PedDisk*& lp_disk, bool strict = true, bool flush = false ) ;
void destroy_device_and_disk( PedDevice*& lp_device, PedDisk*& lp_disk ) ;
bool commit( PedDisk* lp_disk ) ;
bool commit_to_os( PedDisk* lp_disk, std::time_t timeout ) ;
void settle_device( std::time_t timeout ) ;
static PedExceptionOption ped_exception_handler( PedException * e ) ;
std::vector<FS> FILESYSTEMS ;
static std::map< FILESYSTEM, FileSystem * > FILESYSTEM_MAP ;
std::vector<PedPartitionFlag> flags;
std::vector<Glib::ustring> device_paths ;
bool probe_devices ;
Glib::ustring thread_status_message; //Used to pass data to show_pulsebar method
Glib::RefPtr<Glib::IOChannel> iocInput, iocOutput; // Used to send data to gpart command
};
} //GParted
#endif /* GPARTED_GPARTED_CORE_H */