gparted/include/Utils.h

193 lines
7.1 KiB
C
Raw Normal View History

/* Copyright (C) 2004 Bart
* Copyright (C) 2008, 2009, 2010, 2011, 2012 Curtis Gedak
2004-10-06 09:32:40 -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-10-06 09:32:40 -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-10-06 09:32:40 -06:00
*/
/* UTILS
* Some stuff i need in a lot of places so i dropped in all together in one file.
*/
#ifndef GPARTED_UTILS_H
#define GPARTED_UTILS_H
2004-10-06 09:32:40 -06:00
#include "i18n.h"
2004-10-06 09:32:40 -06:00
#include <gtkmm/label.h>
#include <gtkmm/image.h>
#include <gdkmm/pixbuf.h>
2004-10-06 09:32:40 -06:00
#include <glibmm/ustring.h>
#include <glibmm/spawn.h>
#include <iostream>
#include <ctime>
#include <vector>
2004-10-06 09:32:40 -06:00
#define UUID_STRING_LENGTH 36
//Match RFC 4122 UUID strings. Exclude Nil UUID (all zeros) by excluding
// zero from the version field nibble.
#define RFC4122_NONE_NIL_UUID_REGEXP "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[1-9a-fA-F][[:xdigit:]]{3}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"
2004-10-06 09:32:40 -06:00
namespace GParted
{
typedef long long Sector;
typedef long long Byte_Value;
2004-10-06 09:32:40 -06:00
//Size units defined in bytes
const Byte_Value KIBIBYTE=1024;
const Byte_Value MEBIBYTE=(KIBIBYTE * KIBIBYTE);
const Byte_Value GIBIBYTE=(MEBIBYTE * KIBIBYTE);
const Byte_Value TEBIBYTE=(GIBIBYTE * KIBIBYTE);
const Byte_Value PEBIBYTE=(TEBIBYTE * KIBIBYTE);
const Byte_Value EXBIBYTE=(PEBIBYTE * KIBIBYTE);
const Glib::ustring UUID_RANDOM = _("(New UUID - will be randomly generated)") ;
const Glib::ustring UUID_RANDOM_NTFS_HALF = _("(Half new UUID - will be randomly generated)") ;
extern const Glib::ustring DEV_MAPPER_PATH;
enum FSType
{
// Special partition types and functions
Separate unknown file system type from unsupported actions (!13) PATCHSET OVERVIEW: Forum user wanted to be able to move a partition with unknown content: Topic: Can't move/rezise partition on android device (unknown format) http://gparted-forum.surf4.info/viewtopic.php?id=17742 While GParted isn't going to be able to run any sort of file system check on the unknown content there isn't any reason why such a partition can't be copied or moved so long as the partition stays the same size. GParted can just use it's existing internal block copy routine it uses for copying and moving most partition content. This is no different to a few of the already supported file system types which don't have a check-repair tool: exfat, f2fs, nilfs2, udf, ufs. This patchset introduces a third category called basic file system support to go along with the existing full and unsupported categories. Basic supported file systems will just use GParted's inbuilt capabilities to perform actions so they won't need a derived FileSystem implementation class. Unknown file systems along with all other recognised, but otherwise unsupported, file systems will be assigned to this new basic supported category. THIS PATCH: FS_UNKNOWN is used when GParted is unable to identify the contents of a partition. FS_UNKNOWN is also used to generate a file system support set with no supported actions, in the FileSystem::FS::FS() constructor and in GParted_Core::get_fs(). As support for operations on partitions with unknown content is being added, the second usage will be confusing or even wrong. FS( FS_UNKNOWN ) constructs the no supported actions set, yet GParted will support some actions for the FS_UNKNOWN file system type. Therefore add FS_UNSUPPORTED for the second usage. Closes !13 - Support copying and moving of unsupported partition content
2018-09-10 11:13:15 -06:00
FS_UNSUPPORTED = 0, // Type with no supported actions
FS_UNALLOCATED = 1, // Unallocated space on a partitioned drive
FS_UNKNOWN = 2, // Unrecognised content in a drive or partition
FS_UNFORMATTED = 3, // Create a partition without a file system
FS_CLEARED = 4, // Clear existing file system signatures
FS_OTHER = 5, // Just for showing in the File System Support dialog
FS_EXTENDED = 6,
// Fully supported file system types
FS_BTRFS = 7,
FS_EXFAT = 8, /* Also known as fat64 */
FS_EXT2 = 9,
FS_EXT3 = 10,
FS_EXT4 = 11,
FS_F2FS = 12,
FS_FAT16 = 13,
FS_FAT32 = 14,
FS_HFS = 15,
FS_HFSPLUS = 16,
FS_JFS = 17,
FS_LINUX_SWAP = 18,
FS_LUKS = 19,
FS_LVM2_PV = 20,
FS_MINIX = 21,
FS_NILFS2 = 22,
FS_NTFS = 23,
FS_REISER4 = 24,
FS_REISERFS = 25,
FS_UDF = 26,
FS_XFS = 27,
// Other recognised file system types
FS_APFS = 28,
Recognise ATARAID members (#75) PATCHSET OVERVIEW A user had a Firmware / BIOS / ATARAID array of 2 devices configured as a RAID 0 (stripe) set. On top of that was a GPT with the OS partitions. GParted displays the following errors on initial load and subsequent refresh: Libparted Error (-) Invalid argument during seek for read on /dev/sda [ Retry ] [ Cancel ] [ Ignore ] Libparted Error (-) The backup GPT table is corrupt, but the primary appears OK, so that will be used. [ Ok ] [ Cancel ] This is an Intel Software RAID array which stores metadata at the end of each member device, and so the first 128 KiB stripe of the set is stored in the first 128 KiB of the first member device /dev/sda which includes the GPT for the whole RAID 0 device. Hence when libparted reads member device /dev/sda it finds a GPT describing a block device twice it's size and in results the above errors when trying to read the backup GPT. A more dangerous scenario occurs when using 2 devices configured in an Intel Software RAID 1 (mirrored) set with GPT on top. On refresh GParted display this error for both members, /dev/sda and /dev/sdb: Libparted Warning /!\ Not all of the space available to /dev/sda appears to be used, you can fix the GPT to use all of the space (an extra 9554 blocks) or continue with the current setting? [ Fix ] [ Ignore ] Selecting [Fix] gets libparted to re-write the backup GPT to the end of the member device, overwriting the ISW metadata! Do that twice and both copies of the metadata are gone! Worked example of this more dangerous mirrored set case. Initial setup: # dmraid -s *** Group superset isw_caffbiaegi --> Subset name : isw_caffbiaegi_MyMirror size : 16768000 stride : 128 type : mirror status : ok subsets: 0 devs : 2 spares : 0 # dmraid -r /dev/sda: isw, "isw_caffbiaegi", GROUP, ok, 16777214 sectors, data@ 0 /dev/sdb: isw, "isw_caffbiaegi", GROUP, ok, 16777214 sectors, data@ 0 # wipefs /dev/sda offset type --------------------------------------------- 0x200 gpt [partition table] 0x1fffffc00 isw_raid_member [raid] Run GParted and click [Fix] on /dev/sda. Now the first member has gone: # dmraid -s *** Group superset isw_caffbiaegi --> *Inconsistent* Subset name : isw_caffbiaegi_MyMirror size : 16768000 stride : 128 type : mirror status : inconsistent subsets: 0 devs : 1 spares : 0 # dmraid -r /dev/sdb: isw, "isw_caffbiaegi", GROUP, ok, 16777214 sectors, data@ 0 # wipefs /dev/sda offset type --------------------------------------------- 0x200 gpt [partition table] Click [Fix] on /dev/sdb. Now all members of the array are gone: # dmraid -s no raid disks # dmraid -r no raid disks # wipefs /dev/sdb offset type --------------------------------------------- 0x200 gpt [partition table] So GParted must not run libparted partition table scanning on the member devices in ATARAID arrays. Only on the array device itself. In terms of the UI GParted must show disks which are ATARAID members as whole disk devices with ATARAID member content and detect array busy status to avoid allowing active members from being overwritten while in use. THIS COMMIT Recognise ATARAID member devices and display in GParted as whole device "ataraid" file systems. Because they are recognised as whole device content ("ataraid" file systems) this alone stops GParted running the libparted partition table scanning and avoids the above errors. The list of dmraid supported formats is matched by the signatures recognised by blkid: $ dmraid -l asr : Adaptec HostRAID ASR (0,1,10) ddf1 : SNIA DDF1 (0,1,4,5,linear) hpt37x : Highpoint HPT37X (S,0,1,10,01) hpt45x : Highpoint HPT45X (S,0,1,10) isw : Intel Software RAID (0,1,5,01) jmicron : JMicron ATARAID (S,0,1) lsi : LSI Logic MegaRAID (0,1,10) nvidia : NVidia RAID (S,0,1,10,5) pdc : Promise FastTrack (S,0,1,10) sil : Silicon Image(tm) Medley(tm) (0,1,10) via : VIA Software RAID (S,0,1,10) dos : DOS partitions on SW RAIDs $ fgrep -h _raid_member util-linux/libblkid/src/superblocks/*.c .name = "adaptec_raid_member", .name = "ddf_raid_member", .name = "hpt45x_raid_member", .name = "hpt37x_raid_member", .name = "isw_raid_member", .name = "jmicron_raid_member", .name = "linux_raid_member", .name = "lsi_mega_raid_member", .name = "nvidia_raid_member", .name = "promise_fasttrack_raid_member", .name = "silicon_medley_raid_member", .name = "via_raid_member", As they are all types of Firmware / BIOS / ATARAID arrays, report all members as a single "ataraid" file system type. (Except for "linux_raid_member" in the above blkid source listing which is Linux Software RAID). Closes #75 - Errors with GPT on RAID 0 ATARAID array
2019-11-02 11:07:12 -06:00
FS_ATARAID = 29,
FS_BITLOCKER = 30,
FS_GRUB2_CORE_IMG = 31,
FS_ISO9660 = 32,
FS_LINUX_SWRAID = 33,
FS_LINUX_SWSUSPEND = 34,
FS_REFS = 35,
FS_UFS = 36,
FS_ZFS = 37,
// Partition space usage colours
Recognise ATARAID members (#75) PATCHSET OVERVIEW A user had a Firmware / BIOS / ATARAID array of 2 devices configured as a RAID 0 (stripe) set. On top of that was a GPT with the OS partitions. GParted displays the following errors on initial load and subsequent refresh: Libparted Error (-) Invalid argument during seek for read on /dev/sda [ Retry ] [ Cancel ] [ Ignore ] Libparted Error (-) The backup GPT table is corrupt, but the primary appears OK, so that will be used. [ Ok ] [ Cancel ] This is an Intel Software RAID array which stores metadata at the end of each member device, and so the first 128 KiB stripe of the set is stored in the first 128 KiB of the first member device /dev/sda which includes the GPT for the whole RAID 0 device. Hence when libparted reads member device /dev/sda it finds a GPT describing a block device twice it's size and in results the above errors when trying to read the backup GPT. A more dangerous scenario occurs when using 2 devices configured in an Intel Software RAID 1 (mirrored) set with GPT on top. On refresh GParted display this error for both members, /dev/sda and /dev/sdb: Libparted Warning /!\ Not all of the space available to /dev/sda appears to be used, you can fix the GPT to use all of the space (an extra 9554 blocks) or continue with the current setting? [ Fix ] [ Ignore ] Selecting [Fix] gets libparted to re-write the backup GPT to the end of the member device, overwriting the ISW metadata! Do that twice and both copies of the metadata are gone! Worked example of this more dangerous mirrored set case. Initial setup: # dmraid -s *** Group superset isw_caffbiaegi --> Subset name : isw_caffbiaegi_MyMirror size : 16768000 stride : 128 type : mirror status : ok subsets: 0 devs : 2 spares : 0 # dmraid -r /dev/sda: isw, "isw_caffbiaegi", GROUP, ok, 16777214 sectors, data@ 0 /dev/sdb: isw, "isw_caffbiaegi", GROUP, ok, 16777214 sectors, data@ 0 # wipefs /dev/sda offset type --------------------------------------------- 0x200 gpt [partition table] 0x1fffffc00 isw_raid_member [raid] Run GParted and click [Fix] on /dev/sda. Now the first member has gone: # dmraid -s *** Group superset isw_caffbiaegi --> *Inconsistent* Subset name : isw_caffbiaegi_MyMirror size : 16768000 stride : 128 type : mirror status : inconsistent subsets: 0 devs : 1 spares : 0 # dmraid -r /dev/sdb: isw, "isw_caffbiaegi", GROUP, ok, 16777214 sectors, data@ 0 # wipefs /dev/sda offset type --------------------------------------------- 0x200 gpt [partition table] Click [Fix] on /dev/sdb. Now all members of the array are gone: # dmraid -s no raid disks # dmraid -r no raid disks # wipefs /dev/sdb offset type --------------------------------------------- 0x200 gpt [partition table] So GParted must not run libparted partition table scanning on the member devices in ATARAID arrays. Only on the array device itself. In terms of the UI GParted must show disks which are ATARAID members as whole disk devices with ATARAID member content and detect array busy status to avoid allowing active members from being overwritten while in use. THIS COMMIT Recognise ATARAID member devices and display in GParted as whole device "ataraid" file systems. Because they are recognised as whole device content ("ataraid" file systems) this alone stops GParted running the libparted partition table scanning and avoids the above errors. The list of dmraid supported formats is matched by the signatures recognised by blkid: $ dmraid -l asr : Adaptec HostRAID ASR (0,1,10) ddf1 : SNIA DDF1 (0,1,4,5,linear) hpt37x : Highpoint HPT37X (S,0,1,10,01) hpt45x : Highpoint HPT45X (S,0,1,10) isw : Intel Software RAID (0,1,5,01) jmicron : JMicron ATARAID (S,0,1) lsi : LSI Logic MegaRAID (0,1,10) nvidia : NVidia RAID (S,0,1,10,5) pdc : Promise FastTrack (S,0,1,10) sil : Silicon Image(tm) Medley(tm) (0,1,10) via : VIA Software RAID (S,0,1,10) dos : DOS partitions on SW RAIDs $ fgrep -h _raid_member util-linux/libblkid/src/superblocks/*.c .name = "adaptec_raid_member", .name = "ddf_raid_member", .name = "hpt45x_raid_member", .name = "hpt37x_raid_member", .name = "isw_raid_member", .name = "jmicron_raid_member", .name = "linux_raid_member", .name = "lsi_mega_raid_member", .name = "nvidia_raid_member", .name = "promise_fasttrack_raid_member", .name = "silicon_medley_raid_member", .name = "via_raid_member", As they are all types of Firmware / BIOS / ATARAID arrays, report all members as a single "ataraid" file system type. (Except for "linux_raid_member" in the above blkid source listing which is Linux Software RAID). Closes #75 - Errors with GPT on RAID 0 ATARAID array
2019-11-02 11:07:12 -06:00
FS_USED = 38,
FS_UNUSED = 39
} ;
2004-10-06 09:32:40 -06:00
enum SIZE_UNIT
{
UNIT_SECTOR = 0,
UNIT_BYTE = 1,
UNIT_KIB = 2,
UNIT_MIB = 3,
UNIT_GIB = 4,
UNIT_TIB = 5
} ;
class Utils
2004-10-06 09:32:40 -06:00
{
public:
2006-03-28 05:40:29 -07:00
static Sector round( double double_value ) ;
static Gtk::Label * mk_label( const Glib::ustring & text
, bool use_markup = true
, bool wrap = false
, bool selectable = false
Set the xalign property for Gtk::Labels (!40) With the same case as from the previous commit, the very long "Mounted on ..." text is now wrapped, but the text may not be left justified. Slowly adjust the dialog width and see how the text wrapping is updated to fit the size adjustment but the text is centred rather than left justified. This is because setting the halign property to Gtk::ALIGN_START does not guarantee left alignment of text for wrapped or ellipsized Gtk::Labels. Use the xalign property instead. To set the xalign property there is a method in the GtkMisc (Gtk::Misc) base class: gtk_misc_set_alignment (Gtk::Misc::set_alignment) However, GtkMisc (Gtk::Misc) was deprecated in Gtk 3.14 (Gtkmm 3.14) and in Gtk 3.16 (gtkmm 3.16) set_alignment() was replaced with the introduction of two new methods: gtk_label_set_xalign (Gtk::Label::set_xalign) gtk_label_set_yalign (Gtk::Label::set_yalign) Add a check for Gtkmm method Gtk::Label::set_xalign() in configure.ac and use it when available. References: [1] Gtk3 Reference Documentation - gtk_misc_set_alignment() https://developer.gnome.org/gtk3/stable/GtkMisc.html#gtk-misc-set-alignment "gtk_misc_set_alignment has been deprecated since version 3.14 and should not be used in newly-written code. Use GtkWidget's alignment ("halign" and "valign") and margin properties or GtkLabel's "xalign" and "yalign" properties." [2] Gtkmm 3.16 Gtk::Misc Class Reference, set_alignment() method https://developer.gnome.org/gtkmm/3.16/classGtk_1_1Misc.html#a52b2675874cf46a3097938756b9fe9e8 [3] GNOME BugZilla - EmptyBoxes: instructions_label's alignment is off https://bugzilla.gnome.org/show_bug.cgi?id=735841 [4] Gtk commit from 2014-09-16: GtkLabel: add x/yalign properties https://gitlab.gnome.org/GNOME/gtk/commit/d39424fc [5] Gtk3 Reference Documentation - gtk_label_set_xalign() https://developer.gnome.org/gtk3/stable/GtkLabel.html#gtk-label-set-xalign [6] Gtkmm 3.16 Gtk::Label Class Reference, set_xalign() method https://developer.gnome.org/gtkmm/3.16/classGtk_1_1Label.html#acee7d4e87d7cc14080a7b8ded5f84e5e Closes !40 - Limit wrapping labels
2019-05-03 07:42:45 -06:00
, Gtk::Align valign = Gtk::ALIGN_CENTER
) ;
static Gtk::Image* mk_image(const Gtk::StockID& stock_id, Gtk::IconSize icon_size);
static Glib::RefPtr<Gdk::Pixbuf> mk_pixbuf(Gtk::Widget& widget,
const Gtk::StockID& stock_id,
Gtk::IconSize icon_size);
static Glib::ustring get_stock_label(const Gtk::StockID& stock_id);
static Glib::ustring num_to_str( Sector number ) ;
static Glib::ustring get_color(FSType fstype);
static Glib::RefPtr<Gdk::Pixbuf> get_color_as_pixbuf(FSType fstype, int width, int height);
static int get_max_partition_name_length( Glib::ustring & tabletype );
static int get_filesystem_label_maxlength(FSType fstype);
static Glib::ustring get_filesystem_string(FSType fstype);
static const Glib::ustring get_encrypted_string();
static const Glib::ustring get_filesystem_string( bool encrypted, FSType fstype );
static const Glib::ustring get_filesystem_kernel_name( FSType fstype );
static Glib::ustring get_filesystem_software(FSType fstype);
static bool kernel_supports_fs( const Glib::ustring & fs ) ;
static bool kernel_version_at_least( int major_ver, int minor_ver, int patch_ver ) ;
static Glib::ustring format_size( Sector sectors, Byte_Value sector_size ) ;
static Glib::ustring format_time( std::time_t seconds ) ;
static double sector_to_unit( Sector sectors, Byte_Value sector_size, SIZE_UNIT size_unit ) ;
static int execute_command( const Glib::ustring & command ) ;
static int execute_command( const Glib::ustring & command,
Glib::ustring & output,
Glib::ustring & error,
bool use_C_locale = false ) ;
2017-10-20 12:47:00 -06:00
static int execute_command( const Glib::ustring & command,
const char * input,
Glib::ustring & output,
Glib::ustring & error,
bool use_C_locale = false );
Implement shell style exit status decoding (#754684) Command exit status is a 1 byte value between 0 and 255. [1][2] However at the Unix API level the value is encoded as documented in the waitpid(2) manual page. This is true for the Glib API too. [3] This is why, for example, the comment in ext2::check_repair() reported receiving undocumented exit status 256. It was actually receiving exit status 1 encoded as per the waitpid(2) method. Add shell style exit status decoding [2] to execution of all external commands. Return value from Utils::execute_command() and FileSystem::execute_command() functions are now: 0 - 125 - Exit status from the command 126 - Error executing the command 127 - Command not found 128+N - Command terminated by signal N 255 - Unexpected waitpid(2) condition Also adjust checking of the returned statuses as necessary. [1] Advanced Bash-Scripting Guide: Appendix D. Exit Codes With Special Meanings http://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/exitcodes.html [2] Quote from the bash(1) manual page: EXIT STATUS ... Exit statuses fall between 0 and 255, though as explained below, the shell may use values above 125 specially. ... ... When a command terminates on a fatal signal N, bash uses the value of 128+N as the exit status. If a command is not found, the child process created to execute it returns a status of 127. If a command is found but is not executable, the return status is 126. [3] Quote from the Glib Reference Manual, Spawning Processes section, for function g_spawn_check_exit_status(): https://developer.gnome.org/glib/stable/glib-Spawning-Processes.html#g-spawn-check-exit-status The g_spawn_sync() and g_child_watch_add() family of APIs return an exit status for subprocesses encoded in a platform-specific way. On Unix, this is guaranteed to be in the same format waitpid() returns, ... Bug 754684 - Updates to FileSystem:: and Utils::execute_command() functions
2015-09-06 07:39:07 -06:00
static int get_failure_status( Glib::SpawnError & e );
static int decode_wait_status( int wait_status );
static Glib::ustring regexp_label( const Glib::ustring & text
, const Glib::ustring & pattern
) ;
static Glib::ustring trim( const Glib::ustring & src, const Glib::ustring & c = " \t\r\n" ) ;
static Glib::ustring last_line( const Glib::ustring & src );
static Glib::ustring get_lang() ;
static void tokenize( const Glib::ustring& str,
std::vector<Glib::ustring>& tokens,
const Glib::ustring& delimiters ) ;
static void split( const Glib::ustring& str,
std::vector<Glib::ustring>& result,
const Glib::ustring& delimiters ) ;
static int convert_to_int(const Glib::ustring & src);
static Glib::ustring generate_uuid(void);
Read file system size for mounted ext2/3/4 from superblock (#683255) A user had a 190 MiB partition containing an old ext2 file system. When unmounted it was reported as filling the partition, but when mounted it was reported as having 6% unallocated space. The file system's inode tables were approximately twice the size of those created by default with the current mkfs.ext2 defaults. To create an equivalent file system in a 190 MiB partition: mkfs.ext2 -N 97344 /dev/sda15 It turns out that for ext2, ext3 and ext4 file systems what was described as intrinsic unallocated space during the development of Bug #499202 is actually file system overhead. When mounted the ext2/3/4 kernel code reports the size of the file system after subtracting the overhead. Overhead is made up of superblock backups, group descriptors, allocation bitmaps and largest of all inode tables. E2fsprogs tools don't subtract this overhead when reporting the file system size. References: * The Second Extended File System, Internal Layout, by Dave Poirier http://www.nongnu.org/ext2-doc/ext2.html * Linux ext2_statfs() function http://lxr.linux.no/#linux+v3.5.3/fs/ext2/super.c#L1311 Call the file system specific method for reading the usage of ext2, ext3 and ext4 file systems while mounted. Make it read the file system size from the on disk superblock to avoid subtraction of overhead and use the statvfs() system call to return an up to date free space figure. Bug #683255 - ext2: statvfs differs from dumpe2fs (x MB unallocated space within the partition)
2012-09-12 16:51:49 -06:00
static int get_mounted_filesystem_usage( const Glib::ustring & mountpoint,
Byte_Value & fs_size, Byte_Value & fs_free,
Glib::ustring & error_message ) ;
static Byte_Value floor_size( Byte_Value value, Byte_Value rounding_size ) ;
static Byte_Value ceil_size( Byte_Value value, Byte_Value rounding_size ) ;
private:
static bool get_kernel_version( int & major_ver, int & minor_ver, int & patch_ver ) ;
};
2004-10-06 09:32:40 -06:00
}//GParted
#endif /* GPARTED_UTILS_H */