Commit Graph

789 Commits

Author SHA1 Message Date
Mike Fleetwood 301690d9ff Return and use constant reference from Partition::get_path() (!94)
Closes !94 - Make more getter methods use return-by-constant-reference
2021-11-16 16:08:17 +00:00
Mike Fleetwood 21dd6fe00b Return and use constant reference from Device::get_path() (!94)
A number of GParted methods named get_*() are returning properties and
are return-by-value.  For objects this implies the returned value is
copy constructed and later destroyed when it goes out of scope.  Change
them to use return-by-constant-reference to avoid unnecessary object
duplication.  Just have to make sure the reference goes out of scope
before the referenced object is destroyed to avoid having a reference
(pointer) to freed memory.  Assigning to a local variable instead of
of a local reference still duplicates the object so can be used when the
lifetime of the gotten object needs to be longer that the referenced
object.

Previously done for other getters here:
    d948cbcb91
    Make get_custom_text() and get_generic_text() return by reference

This change just makes Device::get_path() return a constant reference
and updates uses to match to avoid copy constructing the returned value.

Closes !94 - Make more getter methods use return-by-constant-reference
2021-11-16 16:08:17 +00:00
Mike Fleetwood aab269cc53 Make MB_Needed_for_Boot_Record() a static member function
Because it doesn't access any member variables or call any member
methods.
2021-10-27 15:04:20 +00:00
Mike Fleetwood ba1bafc5ac Replace /proc/mounts grep with Mount_Info cache reload and query (!89)
Creating a grep process to check if a particular mount is still mounted
is an unnecessary overhead.  All that is needed is for the Mount_Info
module to refresh it's copy of /proc/mounts and query that.

To keep the code as simple as possible just reload the whole of the
Mount_Info module and query the mount cache to determine if the
particular block device is still mounted at this particular mount point.
This therefore re-reads /proc/mounts (necessary) and /proc/swaps and
/etc/fstab (unnecessary).  This is still much less overhead than
creating a separate grep process.

Closes !89 - Fix unmount error when unmounting below a bind mount point
2021-09-17 15:56:10 +00:00
Mike Fleetwood a7f9ec65cf Reorder parameters to add_mountpoint_entry()
To match the order of the members in struct MountEntry.
2021-08-14 15:57:20 +00:00
Mike Fleetwood f5e6239452 Extract common code into Mount_Info::lookup_uuid_or_label() (#162)
Closes #162 - It is no longer possible to mount a LUKS encrypted file
              system
2021-08-14 15:57:20 +00:00
Mike Fleetwood 49747f656d Resolve UUID= and LABEL= refs when searching Mount_Info (#162)
Implemented the second half of the solution described in the previous
commit.  Resolve UUID= and LABEL= references when searching in the
Mount_Info cache so that mount points of encrypted file systems listed
in /etc/fstab can be found using the later added FS_Info details.

Closes #162 - It is no longer possible to mount a LUKS encrypted file
              system
2021-08-14 15:57:20 +00:00
Mike Fleetwood cf5a264b0e White space tidy-up some of DialogFeatures 2021-07-30 16:12:24 +00:00
Mike Fleetwood 47960037f7 Show online file system labelling in the Features dialog (#163)
Show support for online labelling using a second tick mark in the
Features dialog.  This matches how online grow and shrink are shown.

Closes #163 - Feature request: set label on a mounted btrfs
2021-07-30 16:12:24 +00:00
Mike Fleetwood eb034b1759 Add labelling of mounted btrfs (#163)
Btrfs supports labelling of the file system while it is mounted.  This
was added into Linux kernel 3.10 [1] and btrfs-progs 3.12 [2].  As the
oldest supported distributions have the needed versions or newer,
unconditionally enable without any checking for availability.

    Distro             EOL        Linux kernel   btrfs-progs
    Debian 9           2022-Jun   4.19           4.7.3
    RHEL / CentOS 7    2024-Jun   3.10.0         4.9.1
    Ubuntu 18.04 LTS   2023-Apr   4.15.0         4.15.1

Unmounted btrfs is labelled via the block device containing it, where as
a mounted btrfs is labelled via it's mount point.

    # mkfs.btrfs -L initial_label /dev/sdb1
    # blkid /dev/sdb1
    /dev/sdb1: LABEL="initial_label" ...

    # btrfs filesystem label /dev/sdb1 unmounted_label_2
    # blkid /dev/sdb1
    /dev/sdb1: LABEL="unmounted_label_2" ...

    # mount /dev/sdb1 /mnt/1
    # btrfs filesystem label /dev/sdb1 mounted_label_3
    # blkid /dev/sdb1
    /dev/sdb1: LABEL="mounted_label_3" ...

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a8bfd4abea3da0e28f215e2a2b8c2f1ca27ebe80
    Btrfs: set/change the label of a mounted file system
[2] https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git/commit/?id=619dc61cae1420da2dec48f689d49b9b346abc15
    Btrfs-progs: Change the label of a mounted file system

Closes #163 - Feature request: set label on a mounted btrfs
2021-07-30 16:12:24 +00:00
Mike Fleetwood c4ca7d3e9b Mark remaining get_filesystem_*() methods as returning const strings 2021-04-25 15:49:35 +00:00
Mike Fleetwood 5752682c12 Report this LUKS passphrase request reason as resize (#59)
So far when prompting for the LUKS passphrase the dialog always looks
like this:

    +------------------------------------------------+
    |           LUKS Passphrase /dev/sdb1            |
    +------------------------------------------------+
    | Enter LUKS passphrase to open /dev/sdb1        |
    | Passphrase:    [                             ] |
    |                                                |
    |                                                |
    |                          [ Cancel ] [ Unlock ] |
    +------------------------------------------------+

Specifically the first line of the dialog says the reason to provide the
passphrase is to open the encryption mapping.  Now the passphrase may
also be requested when resizing the encryption mapping, as part of a
resize of check operation, show the appropriate reason in the password
dialog.

Closes #59 - Resize of LUKS2 encrypted file system fails with "Nothing
             to read on input"
2021-04-25 15:49:35 +00:00
Mike Fleetwood d7503fd5ed Add ability for small writes to stdin of operation tracked child processes (#59)
This is the equivalent to what was previously done when adding opening
of LUKS mappings.  Namely to add a way to pass the LUKS passphrase to
'cryptsetup luksOpen' via standard input.  Previously the functionality
was added to Utils::execute_command() [1].  Now it is also needed to
pass the LUKS passphrase to 'cryptsetup resize', which is executed as
part of applying resize and check operations to an encrypted file
system.  So add this functionality to FileSystem::execute_command().

For now writing to stdin is only needed for the one variant of
FileSystem::execute_command() which doesn't have progress tracking
callbacks.  Writing to stdin can easily be added to the other progress
tracking callback variants of execute_command() when needed.

[1] 8dff80edc6
    Add ability for small writes to stdin of child processes (#795617)

Closes #59 - Resize of LUKS2 encrypted file system fails with "Nothing
             to read on input"
2021-04-25 15:49:35 +00:00
Mike Fleetwood 2ccbc3ec92 Extract common code into generate_encryption_mapping_name() (#59)
Closes #59 - Resize of LUKS2 encrypted file system fails with "Nothing
             to read on input"
2021-04-25 15:49:35 +00:00
Mike Fleetwood 83abcd8873 Ask for LUKS passphrase for resize operation as required (#59)
When composing a resize operation on an open encryption mapping, use the
existing LUKS password dialog to prompt for the passphrase, if and only
if 'cryptsetup resize' will prompt and GParted doesn't already have a
password.  'cryptsetup resize' will prompt for a LUKS passphrase when
the passphrase was stored in the kernel keyring service,
key_loc == KEYLOC_KeyRing.  See the previous commit "Capture LUKS
mapping master encryption key location (#59)" for more details.

As commented in the code GParted specifically doesn't support the case
where the LUKS passphrase is changed while GParted is running and it
knew the old passphrase.  When resizing an open encryption mapping
GParted will just pass the old out of date passphrase it knows and the
resize will fail like this:

    # cryptsetup status sdb2_crypt | egrep 'type|key location'
      type:         LUKS2
      key location: keyring
    # dmsetup table --target crypt
    sdb2_crypt: 0 491520 crypt aes-xts-plain64 :64:logon:cryptsetup:3d040240-97ba-4559-af98-72c3be500498-d0 0 8:18 32768

    # echo -n oldpassword | cryptsetup -v --size 491520 resize sdb2_crypt
    No key available with this passphrase.
    Command failed with code -2 (no permission or bad passphrase).
    # echo $?
    2

To work around this either close and restart GParted or close and reopen
the encryption mapping.  The former because GParted doesn't save
passwords across a restart so will prompt and the latter because GParted
will use the wrong old passphrase to try to open the mapping and then
prompt for the correct passphrase until successfully opened.

Closes #59 - Resize of LUKS2 encrypted file system fails with "Nothing
             to read on input"
2021-04-25 15:49:35 +00:00
Mike Fleetwood 099b85fe18 Capture LUKS mapping master encryption key location (#59)
ISSUE OVERVIEW

When GParted tries to resize an open LUKS encryption mapping and the
volume (master) key was stored in the kernel keyring service [1] it
fails like this:

    Check and repair file system ([Encrypted] ext4) on /dev/...(ERROR)
    + calibrate /dev/sdd1                                      (SUCCESS)
    + check file system on /dev/mapper/sdd1_crypt for errors...(SUCCESS)
    + grow encryption volume to fill the partition             (ERROR)
      + cryptsetup -v resize 'sdd1_crypt'                      (ERROR)
          Command failed with code -1 (wrong or missing parameters).
          Nothing to read on input.

This error occurs with cryptsetup >= 2.0, kernel >= 4.10 and LUKS2
format because the crypt Device-Mapper target no longer has the volume
key so cryptsetup resize prompts for a passphrase, but GParted doesn't
provide it.

THIS COMMIT

Additionally capture the location of the volume (master) key location
for active encryption mappings.  Do this the using the same method that
cryptsetup uses [2][3].  Namely if the first character of the KEY is a
":" then the key *was* stored in the kernel keyring service, otherwise
it *is* store in the Device-Mapper crypt target as previously.

    # echo -n badpassword | cryptsetup luksFormat --type luks1 /dev/sdb1 -
    # echo -n badpassword | cryptsetup luksOpen /dev/sdb1 sdb1_crypt
    # cryptsetup status sdb1_crypt | egrep 'type|key location'
      type:         LUKS1
      key location: dm-crypt

    # echo -n badpassword | cryptsetup luksFormat --type luks2 /dev/sdb2 -
    # echo -n badpassword | cryptsetup luksOpen /dev/sdb2 sdb2_crypt
    # cryptsetup status sdb2_crypt | egrep 'type|key location'
      type:         LUKS2
      key location: keyring

    # dmsetup table --target crypt
    sdb1_crypt: 0 520192 crypt aes-xts-plain64 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0 8:17 4096
    sdb2_crypt: 0 491520 crypt aes-xts-plain64 :64:logon:cryptsetup:3d040240-97ba-4559-af98-72c3be500498-d0 0 8:18 32768
                                               ^
First character of the KEY field --------------'

[1] Integration with the kernel keyring service
    https://gitlab.com/cryptsetup/cryptsetup/blob/v2.0.0/docs/Keyring.txt
    "
    Starting with cryptsetup 2.0 we load [Volume Key] VK in kernel
    keyring by default for LUKSv2 devices ...

    In summary, the key description visible in dm-crypt table line is a
    reference to VK that usually no longer exists in kernel keyring
    service if you used cryptsetup to for device activation.
    "

[2] cryptsetup/v2.3.5/lib/libdevmapper.c:_dm_target_query_crypt()
    https://gitlab.com/cryptsetup/cryptsetup/-/blob/v2.3.5/lib/libdevmapper.c#L2031
        if (key_[0] == ':')
            *act_flags |= CRYPT_ACTIVATE_KEYRING_KEY;

[3] cryptsetup/v2.3.5/src/cryptsetup.c:action_status()
    https://gitlab.com/cryptsetup/cryptsetup/-/blob/v2.3.5/src/cryptsetup.c#L839
        log_std("  key location: %s\n", (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) ? "keyring" : "dm-crypt");

Closes #59 - Resize of LUKS2 encrypted file system fails with "Nothing
             to read on input"
2021-04-25 15:49:35 +00:00
Mike Fleetwood c4ef43aa5d Remove coding landmine in get_disk() (#152)
get_disk() is the wrapper around libparted's ped_disk_new() which reads
a disk label from the specified device and if successful creates the in
memory PedDisk object to represent it.  In the case that libparted
doesn't recognise a disk label or a file system, having get_disk() go
and destroy the passed in PedDevice object via parameter lp_device is
very unexpected behaviour hence describing it as a coding landmine.

BACKGROUND

1. Early on GParted only worked with devices with valid disk labels.
   FileSystem.h:open_device_and_disk() required both ped_device_get()
   and ped_disk_new() to succeed or neither to succeed.
2. Commit [1] added support for devices which didn't yet have a disk
   label.  open_device_and_disk() had default parameter strict=true
   added.  While scanning strict=false was passed which allowed
   open_device_and_disk() to return success if only ped_device_get()
   succeeded and ped_disk_new() failed when the disk was empty.  All
   other times open_device_and_disk() was called with default
   strict=true, still requiring both or neither to succeed.
3. Commit [2] added support for whole disk file systems.  The now named
   get_device_and_disk() had it's functionality split between
   get_device() and get_disk().  This result in the code landmine being
   left behind: get_disk() destroying the passed device object if
   default parameter strict=true and no disk label or file system was
   detected.

ANALYSIS

1. Since support for whole disk file systems [2] all current calls to
   get_device_and_disk() let the strict parameter default to true and
   are only called on known partitions within disk labels when applying
   a change to that partition.  Therefore they don't care about the
   behaviour of get_disk(), just that get_device_and_disk() maintains
   that both ped_device_get() and ped_disk_new() succeed or neither
   succeed.
2. Two direct calls to get_disk() where the strict parameter defaults to
   true, from calibrate_partition() and erase_filesystem_signatures(),
   only do so on known partitions within disk labels as part of applying
   a change to that partition.  Therefore ped_disk_new() will succeed
   and so PedDevice isn't deleted when not wanted.
3. The two remaining direct calls to get_disk() where the strict
   parameter is explicitly set to false, from set_device_from_disk() and
   detect_filesystem_in_encryption_mapping(), are when scanning.  As the
   pass strict=false they don't allow the PedDevice deletion to occur if
   no recognised disk label is found.

FIX

Remove the strict parameter from get_disk() and get_device_and_disk() as
it's no longer needed.  Remove the code landmine by removing the side
affect of destroying the PedDevice object if a disk label isn't found.
Make sure get_device_and_disk() maintains the all or nothing behaviour.

Also don't pass lp_device by reference to a pointer to get_disk() so the
code can't change where lp_device points.

[1] 038c5c5d99
    P (special thanks to mantiena-baltix for bringing this issue to my

[2] 51ac4d5648
    Split get_device_and_disk() into two (#743181)

Closes #152 - GParted crashed when trying to probe an encrypted
              partition containing content that libparted doesn't
              recognise
2021-04-15 16:33:01 +00:00
Mike Fleetwood 8280f3eedc Correctly const and assert detect_filesystem() parameters (#152)
As discussed in the previous commit "Don't crash probing libparted
unrecognised encrypted file system (#152)", detect_filesystem() accepted
a NULL lp_device pointer and dereferenced it leading to the crash.
Document the requirement for lp_device parameter to be non-NULL via an
assert and also correctly const the parameters.

This forces needing to const the lp_partition parameter to
get_partition_path() too.  Also assert it's non-NULL requirement.

Closes #152 - GParted crashed when trying to probe an encrypted
              partition containing content that libparted doesn't
              recognise
2021-04-15 16:33:01 +00:00
Mike Fleetwood 1e91cb831b Extract some code into detect_filesystem_in_encryption_mapping() (#148)
To avoid making set_luks_partition() more complicated extract the file
system detection portion into a new function.

Closes 148 - Encrypted file systems are no longer recognised
2021-04-03 17:02:04 +00:00
Mike Fleetwood 1e813d83a5 Make FS_Info (blkid) cache incrementally loadable (#148)
Since changes for issue #131 "GParted hangs when non-named device is
hung" FS_Info cache is initialised, cleared and loaded via one call to
load_cache_for_paths().  It runs blkid for named or found disk devices
and associated found partitions from /proc/partitions, rather than
running blkid and letting it report for all block devices.

To avoid the possibility of using blkid on an encryption mapping on a
non-specified and possibly hung block device GParted can't just specify
all encryption mappings.  Instead only encryption mappings which belong
to the above identified block devices should be probed.  That requires
identifying LUKS encryption data in the block devices first so will
require subsequently loading additional data into the FS_Info cache and
running blkid again.

To accommodate this make the FS_Info cache incrementally loadable,
rather than doing everything in a single call to load_cache_for_paths().
Have a separate clear_cache() call which initialises and clears the
cache and make load_cache_for_paths() just run blkid and insert data for
the named paths.

Closes 148 - Encrypted file systems are no longer recognised
2021-04-03 17:02:04 +00:00
Mike Fleetwood a41e8b03ec Pass constant string by reference to lvm2_pv_size_to_num()
It is common C++ practice to pass a constant object by reference to
avoid constructing a duplicate object for pass by value [1].

[1] How to pass objects to functions in C++?
    https://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c/2139254#2139254
2021-03-10 16:40:44 +00:00
Mike Fleetwood a11c16445b Rename member variable to default_fs
... in class Dialog_Partition_New and slightly refactor the code in
build_filesystems_combo() method which sets it.

Change the name from first_creatable_fs to default_fs to be more
immediately obvious what the variable represents.  As default_fs is used
to index the items in the combo_filesystem derived ComboBox, make it's
type an int to match the type of the parameter passed to
Gtk::ComboBox::set_active() [1].  Initialise default_fs to -1 (no
selection) in the class constructor [2], which also allows removal of
local variable set_first just used to track whether first_creatable_fs
had been assigned yet or not.

[1] gtkmm: Gtk::ComboBox Class Reference, set_active()
    https://developer.gnome.org/gtkmm/stable/classGtk_1_1ComboBox.html#a4f23cf08e85733d23f120935b235096d

[2] C++ FAQ / Should my constructors use "initialization lists" or
    "assignment"?
    https://isocpp.org/wiki/faq/ctors#init-lists
2021-03-04 16:55:06 +00:00
Mike Fleetwood 400fc8397e Rename combobox_change() parameter to combo_type_changed
"Type" was rather a generic name.  Use "combo_type_changed" which makes
it clear that the boolean parameter indicates whether a change to
combo_type or one of the other ComboBoxes triggered this callback.
2021-03-04 16:55:06 +00:00
Mike Fleetwood b1cad17a14 Refactor ::OnReadable() creating get_utf8_char_validated() (#136)
Extract call to GLib's g_utf8_get_char_validated() and the associated
workaround to also read NUL characters into a separate function to make
PipeCapture::OnReadable() a little smaller and simpler, so easier to
understand.

Add max_len > 0 clause into get_utf8_char_validated() like this:
    if (uc == UTF8_PARTIAL && max_len > 0)
so that the NUL character reading workaround is only applied when
max_len specifies the maximum number of bytes to read, rather than
when -1 specifies reading a NUL termination string.  This makes
get_utf8_char_validated() a complete wrapper of
g_utf8_get_char_validated() [1], even though GParted always specifies
the maximum number of bytes to read.

No longer describe the inability to read NUL characters as a bug [2]
since the GLib author's said it wasn't [3].

[1] GLib Reference Manual, Unicode Manipulation Functions,
    g_utf8_get_char_validated ()
    https://developer.gnome.org/glib/stable/glib-Unicode-Manipulation.html#g-utf8-get-char-validated

[2] 8dbbb47ce2
    Workaround g_utf8_get_char_validate() bug with embedded NUL bytes
    (#777973)

[3] Bug 780095 - g_utf8_get_char_validated() stopping at nul byte even
    for length specified buffers
    https://bugzilla.gnome.org/show_bug.cgi?id=780095#18
        "If g_utf8_get_char_validated() encounters a nul byte in the
        middle of a string of given longer length, it returns -2,
        indicating a partial gunichar.  That is not the obvious
        behaviour, but since g_utf8_get_char_validated() has been API
        for a long time, the behaviour cannot be changed.
        "

Closes #136 - 1.2.0: test suite is failing in test_PipeCapture
2021-02-22 16:14:35 +00:00
Mike Fleetwood b7c9b3e5a6 Add support for updating the exFAT UUID (!67)
Also with exfatprogs 1.1.0 [1], tune.exfat and exfatlabel gained the
capability to report and set the exFAT Volume Serial Number [2][3][4].
This is what blkid and therefore GParted reports as the UUID.

Report serial number:

    # tune.exfat -i /dev/sdb1
    exfatprogs version : 1.1.0
    volume serial : 0x772ffe5d
    # echo $?
    0

    # blkid /dev/sdb1
    /dev/sdb1: LABEL="test exfat" UUID="772F-FE5D" TYPE="exfat" PTTYPE="dos"

Set serial number:

    # tune.exfat -I 0xf96ef190 /dev/sdb1
    exfatprogs version : 1.1.0
    New volume serial : 0xf96ef190
    # echo $?
    0

tune.exfat exists in earlier releases of exfatprogs so check it has the
capability by searching for "Set volume serial" in the help output
before enabling this capability.

    # tune.exfat
    exfatprogs version : 1.1.0
    Usage: tune.exfat
            -l | --print-label                    Print volume label
            -L | --set-label=label                Set volume label
            -i | --print-serial                   Print volume serial
            -L | --set-serial=value               Set volume serial
            -V | --version                        Show version
            -v | --verbose                        Print debug
            -h | --help                           Show help

(Note the cut and paste error reporting the set volume serial flag as
'-L' rather than actually '-S').

[1] exfatprogs-1.1.0 version released
    http://github.com/exfaoprogs/exfatprogs/releases/tag/1.1.0

[2] [tools][feature request] Allow To Change Volume Serial Number ("ID")
    #138
    https://github.com/exfatprogs/exfatprogs/issues/138

[3] exfatlabel:add get/set volume serial option
    b4d9c9eeb5

[4] exFAT file system specification, 3.1.11 VolumeSerialNumber Field
    https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification#3111-volumeserialnumber-field

Closes !67 - Add support for reading exFAT usage and updating the UUID
2021-02-17 17:16:48 +00:00
Mike Fleetwood 57507e21e2 Add exFAT file system usage reporting (!67)
exfatprogs 1.1.0 released 2021-02-09 [1] has gained support for
reporting file system usage [2][3] so add that capability to GParted.
It works like this:

    # dump.exfat /dev/sdb1 | egrep 'Volume Length\(sectors\):|Sector Size Bits:|Sector per Cluster bits:|Free Clusters:'
    Volume Length(sectors):                 524288
    Sector Size Bits:                       9
    Sector per Cluster bits:                3
    Free Clusters:                          23585

Unfortunately dump.exfat returns a non-zero status on success so that
can't be used to check for failure:

    # dump.exfat /dev/sdb1
    exfatprogs version : 1.1.0
    -------------- Dump Boot sector region --------------
    Volume Length(sectors):                 524288
    ...
    # echo $?
    192

dump.exfat only writes errors to stderr, so use this to identify failure:

    # dump.exfat /dev/sdb1 1> /dev/null
    # echo $?
    192

    # dump.exfat /dev/zero 1> /dev/null
    invalid block device size(/dev/zero)
    bogus sector size bits : 0
    # echo $?
    234

[1] exfatprogs-1.1.0 version released
    http://github.com/exfaoprogs/exfatprogs/releases/tag/1.1.0

[2] [feature request] File system usage reporting
    https://github.com/exfatprogs/exfatprogs/issues/139

[3] exfatprogs: add dump.exfat
    7ce9b2336b

Closes !67 - Add support for reading exFAT usage and updating the UUID
2021-02-17 17:16:48 +00:00
Mike Fleetwood 25b7382d03 Replace Win_GParted::hbox member with local variables
hbox is a very generic name for a member variable and used as a local
variable in two methods.  Change to local variables instead.
2021-02-10 16:30:14 +00:00
Mike Fleetwood f3740c7ac9 Remove now unused return value from run_blkid_load_cache() (#131)
Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:14 +00:00
Mike Fleetwood e9d4a21bfb Remove now superfluous load_fs_info_cache() (#131)
This method is now only called from one location in the code so put it's
two lines of code there.

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood 52ed42de28 Ensure FS_Info (blkid) cache is populated before first use (#131)
Now we always want to run blkid naming all paths, ensure the FS_Info
cache is explicitly loaded first.  Report an error if not done so and
remove the cache loading code from running blkid without naming all
paths.  Fewer code paths to consider and reason about.

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood d86d9ae830 Remove extra execution of blkid for any unreported paths (#131)
Again on Fedora 31 with a slightly different disk layout to the previous
commit.  sdb is partitioned with 1 empty partition and sdc remains
completely empty:
    # lsblk -o name,maj:min,rm,size,ro,type,fstype,label,mountpoint
    NAME            MAJ:MIN RM  SIZE RO TYPE FSTYPE      LABEL MOUNTPOINT
    sda               8:0    0   20G  0 disk
    |-sda1            8:1    0    1G  0 part ext4              /boot
    \-sda2            8:2    0   19G  0 part LVM2_member
      |-fedora-root 253:0    0   17G  0 lvm  ext4              /
      \-fedora-swap 253:1    0    2G  0 lvm  swap              [SWAP]
    sdb               8:16   0    8G  0 disk
    \-sdb1            8:17   0    1G  0 part
    sdc               8:32   0    8G  0 disk
    sr0              11:0    1 1024M  0 rom
    # blkid -v
    blkid from util-linux 2.34  (libblkid 2.34.0, 14-Jun-2019)
    # blkid /dev/sda /dev/sda1 /dev/sda2 /dev/sdb /dev/sdb1 /dev/sdc
    /dev/sda: PTUUID="5012fb1f" PTTYPE="dos"
    /dev/sda1: UUID="3cd48816-7817-4636-9fec-5f1afe76c1b2" TYPE="ext4" PARTUUID="5012fb1f-01"
    /dev/sda2: UUID="PH94ej-C8xU-bnMJ-UIh8-ZimI-4B7f-dHlZxh" TYPE="LVM2_member" PARTUUID="5012fb1f-02"
    /dev/sdb: PTUUID="1d120b57" PTTYPE="dos"
    /dev/sdb1: PARTUUID="1d120b57-01"

Stracing GParted shows these executions of blkid:
    # strace -f -q -bexecve -eexecve ./gpartedbin 2>&1 1> /dev/null | egrep -v 'ENOENT|SIGCHLD'
    ...
    [pid 160040] execve("/usr/sbin/blkid", ["blkid", "/dev/sda", "/dev/sda1", "/dev/sda2", "/dev/sdb", "/dev/sdb1", "/dev/sdc"], 0xa4e1b0 /* 32 vars */ <detached ...>
    [pid 160041] execve("/usr/sbin/blkid", ["blkid", "/dev/sdc"], 0xa4e1b0 /* 32 vars */ <detached ...>
    ...

On Fedora 31 with blkid from util-linux 2.34 it reports information for
sdb (partitioned drive) and sdb1 (empty partition) with only no
information for sdc (empty whole disk drive).  Hence no FS_Info cache
entry and re-execution of blkid just for sdc.

On older CentOS 7 with the same disk layout blkid reports this:
    # blkid -v
    blkid from util-linux 2.23.2  (libblkid 2.23.0, 25-Apr-2013)
    # blkid /dev/sda /dev/sda1 /dev/sda2 /dev/sdb /dev/sdb1 /dev/sdc
    /dev/sda: PTTYPE="dos"
    /dev/sda1: UUID="e7d559e4-3e1d-4fbc-b034-3fdeb498f44d" TYPE="xfs"
    /dev/sda2: UUID="B7ODFx-BfTE-hq7N-UlrF-f5ML-CPRe-klSy26" TYPE="LVM2_member"
    /dev/sdb: PTTYPE="dos"

And stracing GParted shows these executions of blkid:
    # strace -f -q -bexecve -eexecve ./gpartedbin 2>&1 1> /dev/null | egrep -v 'ENOENT|SIGCHLD'
    ...
    [pid  1889] execve("/sbin/blkid", ["blkid", "/dev/sda", "/dev/sda1", "/dev/sda2", "/dev/sdb", "/dev/sdb1", "/dev/sdc"], 0x10b8b10 /* 26 vars */ <detached ...>
    [pid  1890] execve("/sbin/blkid", ["blkid", "/dev/sdb1"], 0x10b8b10 /* 26 vars */ <detached ...>
    [pid  1891] execve("/sbin/blkid", ["blkid", "/dev/sdc"], 0x10b8b10 /* 26 vars */ <detached ...>
...

This time on CentOS 7 with blkid from util-linux 2.23.2 it reports
information for only sdb (partitioned drive), but not sdb1 (empty
partition) or sdc (empty whole disk drive).  Hence no FS_info cache
entries and re-execution of blkid for both sdb1 and sdc.

GParted needs blkid identification of file system images, LVM Logical
Volumes or any other partitions named on the command line which it
wouldn't normally scan [1].  Now every name of interest is passed to
blkid, additional executions of blkid won't get any extra information
and are redundant.  Therefore remove this unnecessary code.

Note that these last 2 commits remove creation of "blank" cache entries
(just block special with blank fstype and other attributes) when blkid
reports no information for a particular path.  Those entry were needed
to suppress unnecessary additional execution of blkid.  However now that
blkid is only executed once (excluding querying the label) this is no
longer necessary.  All the getter functions return suitable blank values
when no cache entry is found.

[1] e8f0504b13
    Make sure that FS_Info cache is loaded for all named paths (#787181)

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood 8b35892ea5 Pass device and partition names to blkid (#131)
A user reported that GParted would hang at "scanning all devices...",
when a fully working disk was named on the command line, but another
device on the machine was hung.

This can be replicated like this:
(on Ubuntu 20.04 LTS for it's NBD support)

1. Export and import NBD:
    # truncate -s 1G /tmp/disk-1G.img
    # nbd-server -C /dev/null 9000 /tmp/disk-1G.img
    # nbd-client localhost 9000 /dev/nbd0

2. Hang the NBD server and therefore /dev/nbd0:
    # killall -STOP nbd-server

3. Run GParted:
    $ gparted /dev/sda

Tracing GParted shows that execution of blkid never returns.

    # strace -f -tt -q -bexecve -eexecve ./gpartedbin 2>&1 1> /dev/null | fgrep -v ENOENT
    ...
    [pid 37823] 13:56:24.814139 execve("/usr/sbin/mkudffs", ["mkudffs", "--help"], 0x55e2a3f2d230 /* 20 vars */ <detached ...>
    [pid 37814] 13:56:24.829246 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=37823, si_uid=0, si_status=1, si_utime=0, si_stime=0} ---
    [pid 37825] 13:56:25.376796 execve("/usr/sbin/blkid", ["blkid", "-v"], 0x55e2a3f2d230 /* 20 vars */ <detached ...>
    [pid 37824] 13:56:25.380824 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=37825, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
    [pid 37826] 13:56:25.402512 execve("/usr/sbin/blkid", ["blkid"], 0x55e2a3f2d230 /* 20 vars */ <detached ...>

Tracking of blkid shows that it hangs on either the open of or first
read from /dev/nbd0.

    # strace blkid
    ...
    lstat("/dev", {st_mode=S_IFDIR|0755, st_size=4560, ...}) = 0
    lstat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
    stat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
    lstat("/dev", {st_mode=S_IFDIR|0755, st_size=4560, ...}) = 0
    lstat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
    access("/dev/nbd0", F_OK)               = 0
    stat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
    openat(AT_FDCWD, "/sys/dev/block/43:0", O_RDONLY|O_CLOEXEC) = 4
    openat(4, "dm/uuid", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
    close(4)                                = 0
    openat(AT_FDCWD, "/dev/nbd0", O_RDONLY|O_CLOEXEC

Clean up:

1. Resume NBD server:
    # killall -CONT nbd-server

2. Delete NBD setup:
    # nbd-client -d /dev/nbd0
    # killall nbd-server
    # rm /tmp/disk-1G.img

Fix this by making GParted specify the whole disk device and partition
names that it is interested in to blkid, rather than letting blkid scan
and report all block devices.  Do this both when GParted determines the
devices for itself and when they are named on the command line.

Also update example blkid command output being parsed and cache value
with this change to how blkid is executed.

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood 884cd5a352 Read partition names from /proc/partitions too (#131)
GParted already always reads /proc/partitions for whole disk device
names no matter whether it uses whole disk devices named on the command
line, from /proc/partitions or from libparted.  As /proc/partitions
lists all the block devices that the kernel knows about, and therefore
all the possible ones blkid could probe, so use it to provide partition
names and device to partition mapping.  See code comments for more
details about the assumptions the /proc/partition parsing code makes and
the fact that these are confirmed by examining the Linux kernel source.

This commit just adds debugging to print the existing vector of
validated devices GParted shows in the UI and the vector with all
partitions added, ready for but not yet passed to blkid.
    # ./gpartedbin
    ...
    DEBUG: device_paths=["/dev/sda","/dev/sdb"]
    DEBUG: device_and_partition_paths=["/dev/sda","/dev/sda1","/dev/sda2","/dev/sdb","/dev/sdb1"]

Also demonstrating that this continues to support named devices,
including file system image files [1].
    # truncate -s 256M /tmp/ext4.img
    # mkfs.ext4 /tmp/ext4.img
    # ./gpartedbin /dev/sda /tmp/ext4.img
    ...
    DEBUG: device_paths=["/dev/sda","/tmp/ext4.img"]
    DEBUG: device_and_partition_paths=["/dev/sda","/dev/sda1","/dev/sda2","/tmp/ext4.img"]

[1] e8f0504b13
    Make sure that FS_Info cache is loaded for all named paths (#787181)

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood 52930f30ae Refactor load_proc_partitions_info_cache() a bit (#131)
Put whole disk device name matching code into a helper function to make
the /proc/partition parsing code easier to understand.

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood 45f88c3274 Merge FS_Info load cache calls (#131)
Now FS_Info::load_cache() and ::load_cache_for_paths() are nearly next
to each other, merge them together to simplify the code a little.  This
makes the special case to ensure that file system images named on the
command line were queried by blkid and loaded into the FS_Info cache [1]
become the normal cache loading method.  Already passing all discovered
or named devices to load_cache_for_paths() is also a step on the way to
doing it for all devices and partitions of interest.

Just need to ensure that load_cache_for_paths() always loads the cache
as load_cache() did, rather than only when it hadn't already been
loaded.  Otherwise GParted will only ever run blkid and load the cache
once at startup and not on each refresh.

[1] e8f0504b13
    Make sure that FS_Info cache is loaded for all named paths (#787181)

Closes #131 - GParted hangs when non-named device is hung
2021-02-10 16:30:13 +00:00
Mike Fleetwood bd386f445d Add exFAT support (!30)
With exfatprogs (https://github.com/exfatprogs/exfatprogs) installed the
following operations on exFAT file systems are supported:
- Creation
- Checking
- Labelling
As of the current exfatprogs 1.0.4 the following are not supported:
- Reading usage
- Resizing
- Updating the UUID

Closes !30 - Add exFAT support
2021-01-15 19:55:17 +00:00
Mike Fleetwood 15b42f6978 Remove unneeded #include <vector> from TreeView_Detail.h
std::vector<> is no longer used in TreeView_Detail.h since this commit
replaced them:
    fae909897e
    Use PartitionVector class throughout the code (#759726)
2020-09-18 16:00:44 +00:00
Mike Fleetwood 201f5f2f2f Add missing includes into Devices module 2020-05-27 16:02:47 +00:00
Mike Fleetwood 7000fac99a Delete old Fill txtview_device_info_buffer comment
Seems to be referring to how Fill_Label_Device_Info() worked in the
past, but from history before the beginning of the GIT repository.
Remove out of date comment.
2020-03-07 16:34:37 +00:00
Mike Fleetwood 01826277e3 Rename TreeView_Detail::treeview_filesystems_Columns member to fsname (!52)
Closes !52 - Rename members and variables currently named 'filesystem'
2019-12-04 07:38:01 +00:00
Mike Fleetwood e5b92a87f2 Rename DialogFeatures::treeview_filesystems_Columns member to fsname (!52)
Name the structure member to 'fsname' used to store strings like "ext2"
etc.  This is equivalent to what was previously done in this commit:
    a9f08ddc7d
    Rename local variable to fsname in get_filesystem() (#741430)

Closes !52 - Rename members and variables currently named 'filesystem'
2019-12-04 07:38:01 +00:00
Mike Fleetwood f53c462c06 Rename create_format_menu_add_item() parameter of type FSType (!52)
Closes !52 - Rename members and variables currently named 'filesystem'
2019-12-04 07:38:00 +00:00
Mike Fleetwood c85fc66dcf Rename Utils method parameters of type FSType (!52)
Closes !52 - Rename members and variables currently named 'filesystem'
2019-12-04 07:38:00 +00:00
Mike Fleetwood 58fb230fb0 Also rename FS.filesystem member to fstype (!52)
Closes !52 - Rename members and variables currently named 'filesystem'
2019-12-04 07:37:19 +00:00
Mike Fleetwood b0f92be638 Rename Partition.filesystem member to fstype (!52)
Previously made this change:
    175d27c55d
    Rename enum FILESYSTEM to FSType

Now complete the renaming exercise of members and variables currently
named 'filesystem'.

Closes !52 - Rename members and variables currently named 'filesystem'
2019-12-03 13:24:44 +00:00
Mike Fleetwood fa682d372a Make 4 internally used only DMRaid methods private 2019-12-02 16:35:22 +00:00
Mike Fleetwood 21cad97dc7 Recognise ATARAID members started by dmraid (#75)
This is not strictly necessary as members are already recognised using
blkid since this commit earlier in the sequence "Recognise ATARAID
members (#75)".  However it makes sure active members are recognised
even if blkid is not available and matches how file system detection
queries the SWRaid_Info module.

Closes #75 - Errors with GPT on RAID 0 ATARAID array
2019-12-02 16:35:22 +00:00
Mike Fleetwood bb865aaaa4 Display array device as mount point of dmraid started ATARAID members (#75)
This matches how the array device is displayed as the mount point for
mdadm started ATARAID members by "Display array device as mount point of
mdadm started ATARAID members (#75)" earlier in this patchset.

Extend the DMRaid module member cache to save the array device name and
use as needed to display as the mount point.

Closes #75 - Errors with GPT on RAID 0 ATARAID array
2019-12-02 16:35:22 +00:00
Mike Fleetwood caec22871e Detect busy status of dmraid started ATARAID members (#75)
Again this is to stop GParted allowing overwrite operations being
performed on an ATARAID member while the array is actively using the
member.  This time for dmraid started arrays using the kernel DM (Device
Mapper) driver.

The DMRaid module already uses dmraid to report active array names:

    # dmraid -sa -c
    isw_ecccdhhiga_MyArray

To find active members in this array, (1) use udev to lookup the kernel
device name:

    # udevadm info --query=name /dev/mapper/isw_ecccdhhiga_MyArray
    dm-0

(2) list the member names exposed by the kernel DM driver through the
/sys file system.

    # ls /sys/block/dm-0/slaves
    sdc  sdd
    # ls -l /sys/block/dm-0/slaves
    lrwxrwxrwx 1 root root 0 Nov 24 09:52 sdc -> ../../../../pci0000:00/0000:00:0d.0/ata3/host2/target2:0:0/2:0:0:0/block/sdc
    lrwxrwxrwx 1 root root 0 Nov 24 09:52 sdc -> ../../../../pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd

Closes #75 - Errors with GPT on RAID 0 ATARAID array
2019-12-02 16:35:22 +00:00
Mike Fleetwood ef6794b7de Display correct type of mdadm recognised ATARAID members (#75)
The previous commit, made mdadm recognised IMSM and DDF type ATARAID
members get displayed as "linux-raid" (Linux Software RAID array
member).  This was because of query method 1 in detect_filesystems().

Fix this now by exposing and using the fstype of the member from the
SWRaid_Info cache.

Closes #75 - Errors with GPT on RAID 0 ATARAID array
2019-12-02 16:35:22 +00:00