Commit Graph

3746 Commits

Author SHA1 Message Date
Mike Fleetwood 3140b76a80 Print OS details in the GitLab CI (!48)
Just a simple debugging aid to have the OS details printed in the GitLab
CI output.

Closes !48 - Remain with CentOS 7 for GitLab CI
2019-10-03 15:36:06 +00:00
Mike Fleetwood 22984637b0 Remain with CentOS 7 for GitLab CI (!48)
When GParted GitLab Continuous Integration was setup, CentOS 7 image was
used for a slow moving distribution and Ubuntu as a different, faster
moving distribution.

CentOS 8 has recently been released [1].  To avoid automatically
switching to it when an official CentOS 8 docker image is made available
[2], explicitly specify the CentOS 7 image.

[1] Release for CentOS Linux 8 and CentOS Streams (2019-09-24)
    https://lists.centos.org/pipermail/centos-announce/2019-September/023449.html

[2] Docker Official Images, The official build of CentOS
    https://hub.docker.com/_/centos/

Closes !48 - Remain with CentOS 7 for GitLab CI
2019-10-03 15:36:06 +00:00
Marek Černocký 7567069c0b Updated Czech help translation 2019-10-02 15:00:26 +02:00
Marek Černocký 8b867379bb Updated Czech translation 2019-10-02 10:35:31 +02:00
Jordi Mas ec16f98bef Update Catalan translation 2019-09-19 22:04:53 +02:00
Anders Jonsson 2f41fd793e Update Swedish translation 2019-08-22 16:30:27 +00:00
Jordi Mas 88e3d52380 Update Catalan translation 2019-08-13 18:52:11 +02:00
Asier Sarasua Garmendia 1a8193909e Update Basque translation 2019-08-13 07:51:57 +00:00
Daniel Șerbănescu cf33efc5c6 Update Romanian translation 2019-08-11 07:22:06 +00:00
Mathias L. Baumann f77fd00cb5 Fix invalid substitution in de.po (!47)
Fixes the error:
  (gpartedbin:995): glibmm-WARNING **: 09:11:54.522: invalid
  substitution "%2" in fmt string "%2 Operationen stehen momentan aus."

Closes !47 - Fix invalid substitution in de.po
2019-07-22 17:48:55 +01:00
Mike Fleetwood 7afc39a707 Erase correct key in unit test PasswordRAMStoreTest.TooLongPassword
Was attempting to erase the wrong key "key-long" for the test.  It
should be erasing "key-too-long".  Fix this.  Given that that line in
the test was to erase a non-existent key and confirm failure; the test
passed before with the wrong non-existent key, and still passes with the
right non-existent key.  Clearly a cut and paste error as a result of
copying the previous LongPassword test when initially added in:
    c6657aab9e
    Add unit tests for PasswordRAMStore module (#795617)
2019-07-18 15:27:43 +00:00
Mike Fleetwood a4c00e03e6 Drop use of long ago removed udevsettle
Separate udevsettle command was merged into udevadm back in udev 117
(released 2007-11-13) by:
    225cb03bd8
    udevadm: merge all udev tools into a single binary

The oldest supported distributions have these much newer versions of
udev:
  Distro             EOL        udevadm -V
  Debian 8           2020-Apr   215 (combined systemd and udev)
  RHEL / CentOS 7    2024-Jun   219 (combined systemd and udev)
  Ubuntu 16.04 LTS   2021-Apr   229 (combined systemd and udev)
2019-07-18 15:27:43 +00:00
Mike Fleetwood df65fbd468 Order internally detected signatures by increasing offset (!46)(#16)
Along with the previous patch "Avoid reading the same sector multiple
times in a row (!46)(#16)" internal detection of file system signatures
now reads the minimum number of sectors in increasing order.

As the code still considers the sector size, it now also reads less
sectors from devices with larger sectors to get all the signatures.  So
on a 512 byte sector device it maximally seeks to and reads from these
byte offsets:
    0, 512, 1024, 65536
and on a 4096 byte sector device, only from these byte offsets:
    0, 65536

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
Closes #16 - "invalid argument for seek()" error on very small (<=40KiB)
             drives
2019-07-18 15:27:43 +00:00
Mike Fleetwood 869ebb71ea Avoid reading the same sector multiple times in a row (!46)(#16)
GParted internal file system detection is reading the same sector
multiple times in a row.  Add an optimisation to only read a sector if
it is different to the previously read sector.

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
Closes #16 - "invalid argument for seek()" error on very small (<=40KiB)
             drives
2019-07-18 15:27:43 +00:00
Mike Fleetwood 5bb3415bcb Just pass sector size to detect_filesystem_internal() (!46)(#16)
After the previous commit the lp_device structure pointer parameter is
only used to provide sector_size.  Just pass that instead.

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
Closes #16 - "invalid argument for seek()" error on very small (<=40KiB)
             drives
2019-07-18 15:27:43 +00:00
Mike Fleetwood 228374fe50 Switch to POSIX open() in detect_filesystem_internal() (!46)(#16)
For every partitioned device that GParted scans it triggers a set of
udev change events from it's internal file system signature detection
function.  This is the sequence of events:

  gparted    |set_devices_thread(pdevices)  pdevices->["/dev/sdb"]
  gparted    |  ped_device_get("/dev/sdb")
  libparted  |      open("/dev/sdb", O_RDONLY) = 8
  libparted  |      close(8)
  gparted    |  useable_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |    open("/dev/sdb", O_RDONLY|O_NONBLOCK) = 8
  gparted    |    read(8, ...)
  gparted    |    close(8)
  gparted    |  set_device_from_disk(device, device_path="/dev/sdb")
  gparted    |    get_device(device_path="/dev/sdb", ..., flush=true)
  gparted    |      ped_device_get()
  gparted    |      flush_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |        ped_device_open()
  libparted  |          open("/dev/sdb", O_RDWR) = 8
  gparted    |        ped_device_sync()
  gparted    |        ped_device_close()
  libparted  |          close(8)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|            KERNEL change /devices/.../sdb (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   change /devices/.../sdb (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |        settle_device()
  gparted    |          Utils::execute_command("udevadm settle --timeout=1")
  gparted    |    detect_filesystem(lp_device, NULL, ...)  lp_device->path="/dev/sdb"
  gparted    |      detect_filesystem_internal(lp_device, NULL)  lp_device->path="/dev/sdb"
  gparted    |        ped_device_open()
  libparted  |          open("/dev/sdb", O_RDWR) = 8
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_close()
  libparted  |          close(8)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|            KERNEL change /devices/.../sdb (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   change /devices/.../sdb (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |    get_disk(lp_device, lp_disk, strict=false)
  gparted    |      ped_disk_new(lp_device)  lp_device->path="/dev/sdb"
  libparted  |        open("/dev/sdb", O_RDWR) = 8
  libparted  |        close(8)
  udev(async)|          KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|          KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|          KERNEL change /devices/.../sdb (block)
  udev(async)|          KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|          KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|          UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|          UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|          UDEV   change /devices/.../sdb (block)
  udev(async)|          UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|          UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |      settle_device()
  gparted    |        Utils::execute_command("udevadm settle --timeout=1")
  gparted    |    set_device_partitions()
  gparted    |      detect_filesystem()
  gparted    |      set_partition_label_and_uuid(partition)  partition.get_path()="/dev/sdb1"
  gparted    |        read_label()
  gparted    |          ext2::read_label()
  gparted    |            Utils::execute_command("e2label /dev/sdb1")

Note that the udev block device change events triggered in
detect_filesystem_internal() occur before the waited for ones in the
second commit "Wait for udev to recreate /dev/PTN entries when querying
partition FSs (!46)" in get_disk() so these were already waited for.

The call chain is:
    set_devices_thread()
        set_device_from_disk()
            detect_filesystem()
                detect_filesystem_internal()
                    ped_device_open()
                    ped_device_read()
                    ped_device_close()

This occurs because file system detection is performed on whole disk
devices, but the device contains a partition table, so blkid won't
report any content GParted accepts as a file system, so it tries it's
own internal detection.

Fix this by changing detect_filesystem_internal() to use POSIX open(),
read() and close() so the file can be opened read-only and udev change
events aren't triggered.

Note that when using detect_filesystem_internal() on a partition this
also changes the device it reads from.  Before it used libparted which
always reads from the whole disk device, now it reads from the partition
device.  This doesn't matter because GParted ensures the data is
consistent between them [2] and blkid reads from each partition device
which GParted already uses.

As the new code avoids using the libparted API, and just skips to the
next signature on lseek() and read() errors, it therefore won't generate
libparted exceptions such as this when scanning very small drives:
    Invalid argument during seek for read on /dev/PTN

[1] f8faee6377
    Avoid whole disk FAT being detected as MSDOS partition table
    (#743181)

[2] 3bea067596
    Flush devices when scanning to prevent reading stale signatures
    (#723842)

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
Closes #16 - "invalid argument for seek()" error on very small (<=40KiB)
             drives
2019-07-18 15:27:43 +00:00
Mike Fleetwood 7289d4c52a Pass unmodified parameter to useable_device() as const (!46)
GParted_Core::useable_device() doesn't change the pointed to PedDevice
structure.  Pass it as const so the compiler enforces this.

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
2019-07-18 15:27:43 +00:00
Mike Fleetwood e5898e5813 Switch to POSIX open() in useable_device() (!46)
For every device that GParted scans, it determines if it can be used by
attempting to read the first sector.  This is the sequence of events,
as reported in the previous two commit messages:

  gparted    |set_devices_thread(pdevices)  pdevices->["/dev/sdb"]
  ...
  gparted    |  useable_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |    ped_device_open()
  libparted  |      open("/dev/sdb", O_RDWR) = 8
  gparted    |    ped_device_read()
  gparted    |    ped_device_close()
  libparted  |      close(8)
  udev(async)|        KERNEL change /devices/.../sdb (block)
  ...
  udev(async)|        UDEV   change /devices/.../sdb (block)

Note that these udev block device change events occur before the ones
waited for in the first commit "Wait for udev change on /dev/DISK when
querying whole device FS (!46)" so these were already waited for.

So because libparted only opens devices read-write this triggers a set
of udev change events for the whole block device, and if the device is
partitioned, also remove and re-add events for all the partitions.

Switch to using POSIX open(), read() and close() calls so read-only
access can be specified to avoid the unnecessary udev change events.

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
2019-07-18 15:27:43 +00:00
Mike Fleetwood f170a1e542 Wait for udev to recreate /dev/PTN entries when querying partition FSs (!46)
After the previous fix, on my CentOS 7 VM, GParted is now often
reporting a warning that the /dev/PTN entry is missing when reading the
label of the file system in the first partition.  This happens
regardless of the file system type.

Example error for EXT4:
    e2label: No such file or directory while trying to open /dev/sdb1
    Couldn't find valid file system superblock.

Example error for XFS:
    /dev/sdb1: No such file or directory
    fatal error -- couldn't initialize XFS library

As with the case in the previous commit, GParted gets the label via
blkid instead.

Again with debugging and sleeping in GParted, stracing the GParted
thread GParted_Core::set_devices_thread() and using 'udevadm monitor' to
watch udev events the following sequence of events is observed:

  gparted    |set_devices_thread(pdevices)  pdevices->["/dev/sdb"]
  gparted    |  ped_device_get("/dev/sdb")
  libparted  |      open("/dev/sdb", O_RDONLY) = 8
  libparted  |      close(8)
  gparted    |  useable_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |    ped_device_open()
  libparted  |      open("/dev/sdb", O_RDWR) = 8
  gparted    |    ped_device_read()
  gparted    |    ped_device_close()
  libparted  |      close(8)
  udev(async)|        KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|        KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|        KERNEL change /devices/.../sdb (block)
  udev(async)|        KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|        KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|        UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|        UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|        UDEV   change /devices/.../sdb (block)
  udev(async)|        UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|        UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |  set_device_from_disk(device, device_path="/dev/sdb")
  gparted    |    get_device(device_path="/dev/sdb", ..., flush=true)
  gparted    |      ped_device_get()
  gparted    |      flush_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |        ped_device_open()
  libparted  |          open("/dev/sdb", O_RDWR) = 8
  gparted    |        ped_device_sync()
  gparted    |        ped_device_close()
  libparted  |          close(8)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|            KERNEL change /devices/.../sdb (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   change /devices/.../sdb (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |        settle_device()
  gparted    |          Utils::execute_command("udevadm settle --timeout=1")
  gparted    |    detect_filesystem(lp_device, NULL, ...)  lp_device->path="/dev/sdb"
  gparted    |      detect_filesystem_internal(lp_device, NULL)  lp_device->path="/dev/sdb"
  gparted    |        ped_device_open()
  libparted  |          open("/dev/sdb", O_RDWR) = 8
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_read()
  gparted    |        ped_device_close()
  libparted  |          close(8)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|            KERNEL change /devices/.../sdb (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|            KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|            UDEV   change /devices/.../sdb (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|            UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |    get_disk(lp_device, lp_disk, strict=false)
  gparted    |      ped_disk_new(lp_device)  lp_device->path="/dev/sdb"
  libparted  |        open("/dev/sdb", O_RDWR) = 8
  libparted  |        close(8)
  udev(async)|          KERNEL remove /devices/.../sdb/sdb1 (block)
  udev(async)|          KERNEL remove /devices/.../sdb/sdb2 (block)
  udev(async)|          KERNEL change /devices/.../sdb (block)
  udev(async)|          KERNEL add    /devices/.../sdb/sdb1 (block)
  udev(async)|          KERNEL add    /devices/.../sdb/sdb2 (block)
  udev(async)|          UDEV   remove /devices/.../sdb/sdb1 (block)
  udev(async)|          UDEV   remove /devices/.../sdb/sdb2 (block)
  udev(async)|          UDEV   change /devices/.../sdb (block)
  udev(async)|          UDEV   add    /devices/.../sdb/sdb1 (block)
  udev(async)|          UDEV   add    /devices/.../sdb/sdb2 (block)
  gparted    |    set_device_partitions()
  gparted    |      detect_filesystem()
  gparted    |      set_partition_label_and_uuid(partition)  partition.get_path()="/dev/sdb1"
  gparted    |        read_label()
  gparted    |          ext2::read_label()
  gparted    |            Utils::execute_command("e2label /dev/sdb1")

So in this case for a partitioned drive, libparted ped_disk_new() is
opening and closing the device read-write and triggering the udev remove
and add partition block special entries exactly when the label is trying
to be read from the first partition, causing the device missing error.
The call chain is:
    set_devices_thread()
        set_device_from_disk()
            get_disk()
                ped_disk_new()

Looking at the source for ped_disk_new() [1] it is calling
ped_device_open() and ped_device_close(), hence why it is opening the
device read-write and triggering the udev events.

Looking back at commit "Wait for udev to recreate /dev/PTN entries when
calibrating (#762941)" [2] and re-testing it, the udev events were also
caused by ped_disk_new() with this call chain:
    apply_operation_to_disk()
        calibrate_partition()
            get_disk()
                ped_disk_new()

Fix this probe case and keep the fix for the previous calibrate case by
moving the waiting for udev events from calibrate_partition() into
get_disk(), right after ped_disk_new().  The maximum wait time is
shortened to the shorter 1 second probing timeout to avoid the longer
10 second apply timeout in this probing case.  The calibrate case commit
message said "The longest I have seen udev take to do this is 0.80
seconds in a VM".

[1] parted/libparted/disk.c:ped_disk_new()
    http://git.savannah.gnu.org/cgit/parted.git/tree/libparted/disk.c?id=v3.2#n169

[2] fd9013d5f6
    Wait for udev to recreate /dev/PTN entries when calibrating
    (#762941)

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
2019-07-18 15:27:43 +00:00
Mike Fleetwood 1382e0b828 Wait for udev change on /dev/DISK when querying whole device FS (!46)
GParted nearly always shows this warning against a whole disk device
FAT32 file system on my development VMs:
    plain floppy: device "/dev/sdb" busy (Resource temporarily
    unavailable): Cannot initialize '::'
    mlabel: Cannot initialize drive
However GParted does get the label via blkid instead.  Occasionally
everything works correctly and there is no warning.

Never found a similar error for any other file system on a whole disk
device.  The timing never seems to clash.

Remember that when a writable file descriptor of a disk device is
closed, udev events are triggered which update the kernel and /dev
entries for any partition changes.  (This is in addition to coding which
has always existed in the partitioning tools, including fdisk and
parted, to inform the kernel, but not create /dev entries, of partition
changes).

With debugging and sleeping in GParted, stracing the GParted thread
GParted_Core::set_devices_thread() and using 'udevadm monitor' to watch
udev events the following sequence of events is observed:

  gparted    |set_devices_thread(pdevices)  pdevices->["/dev/sdb"]
  gparted    |  ped_device_get("/dev/sdb")
  libparted  |      open("/dev/sdb", O_RDONLY) = 8
  libparted  |      close(8)
  gparted    |  useable_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |    ped_device_open()
  libparted  |      open("/dev/sdb", O_RDWR) = 8
  gparted    |    ped_device_read()
  gparted    |    ped_device_close()
  libparted  |      close(8)
  udev(async)|        KERNEL change /devices/.../sdb (block)
  udev(async)|        KERNEL change /devices/.../sdb (block)
  udev(async)|        UDEV   change /devices/.../sdb (block)
  udev(async)|        UDEV   change /devices/.../sdb (block)
  gparted    |  set_device_from_disk(device, device_path="/dev/sdb")
  gparted    |    get_device(device_path="/dev/sdb", ..., flush=true)
  gparted    |      ped_device_get()
  gparted    |      flush_device(lp_device)  lp_device->path="/dev/sdb"
  gparted    |        ped_device_open()
  libparted  |          open("/dev/sdb", O_RDWR) = 8
  gparted    |        ped_device_sync()
  gparted    |        ped_device_close()
  libparted  |          close(8)
  udev(async)|            KERNEL change /devices/.../sdb (block)
  udev(async)|            KERNEL change /devices/.../sdb (block)
  udev(async)|            UDEV   change /devices/.../sdb (block)
  udev(async)|            UDEV   change /devices/.../sdb (block)
  gparted    |    set_device_one_partition()
  gparted    |      set_partition_label_and_uuid()
  gparted    |        read_label()
  gparted    |          fat16::read_label()
  gparted    |            Utils::execute_command("mlabel -s :: -i /dev/sdb")

This sequence of events only shows which close()s by libparted trigger
udev events.  It does not show that processing those events are
asynchronous and overlap with GParted executing mlabel, causing the
device busy error.

As libparted's ped_device_open() doesn't offer a way to specify that a
device will only be used for reading, it always opens it read-write
[1][2].  Hence this sequence in GParted_Core::flush_device():
    ped_device_open()
    ped_device_sync()
    ped_device_close()
always triggers udev change events on the whole disk device.  Fix by
waiting for those udev events to complete.

[1] libparted documentation, PedDevice, ped_device_open()
    https://www.gnu.org/software/parted/api/group__PedDevice.html#ga7c87bd06e76553c8ff3262b5e6ca256

[2] parted/libparted/arch/linux.c:linux_open()
    http://git.savannah.gnu.org/cgit/parted.git/tree/libparted/arch/linux.c?id=v3.2#n1628

Closes !46 - Whole device FAT32 file system reports device busy warning
             from mlabel
2019-07-18 15:27:43 +00:00
Rafael Fontenelle be52d8636e Update Brazilian Portuguese translation 2019-07-18 13:06:48 +00:00
Mike Fleetwood 3f15a66291 Drop use of long ago removed udevinfo
The last distribution to include the separate 'udevinfo' command was
RHEL / CentOS 5 with udev 095.  All supported distributions have much
newer versions of udev and instead have the 'udevadm' command.
2019-07-04 10:51:50 -06:00
Mike Fleetwood 5a52b44071 Switch to faster minfo and mdir to read FAT16/32 usage (#569921)
A user reported that GParted was slow to refresh on FAT32 file systems:
"can take very long, up to several minutes; can be reproduced by running
dosfsck manually".  This is because the file system was large and almost
full, and GParted performs a file system check just to to report the
file system usage.

Created a 4 GiB FAT32 file system and almost filled it with 4 KiB files,
just over 970,000 files.

    # df -k /mnt/2
    Filesystem     1K-blocks     Used Available Used% Mounted on
    /dev/sdb2        4186108 39155384    270724   94% /mnt/2
    # df -i /mnt/2
    Filesystem     Inodes IUsed IFree IUse% Mounted on
    /dev/sdb2           0     0     0     - /mnt/2
    # find /mnt/2 -type f -print | wc -l
    971059
    # find /mnt/2 -type d -print | wc -l
    1949

Testing performance of the current fsck.fat:

    # time fsck.fat -n -v /dev/sdb2 | \
    > egrep 'bytes per logical sector|bytes per cluster|sectors total|clusters$'
           512 bytes per logical sector
          4096 bytes per cluster
       8388608 sectors total
    /dev/sdb2: 973008 files, 978846/1046527 clusters

    real    0m11.552s
    user    0m2.183s
    sys     0m7.547s

Free sectors in the file system according to fsck.fat:
    (1046527 - 978846) * 4096 / 512 = 541448 sectors

Repeating this test while also using 'blktrace /dev/sdb2' and Ctrl-C
around the test in a separate terminal, reports these numbers of I/Os
being performed:
    Read requests   Read bytes
           15,563      165 MiB

Prior to this commit [1] from 0.0.9, GParted used libparted's
ped_file_system_get_resize_constraint() to report the minimum size to
which a FAT* file system can be resized.  Use this test program [2] to
performance test this method:

    # time ./fscons /dev/sdb2
    dev=/dev/sdb2
    sector_size=512
    min_size=7909522
    max_size=8388608

    real    0m2.673s
    user    0m0.070s
    sys     0m1.834s

Free sectors in the file system according to libparted
ped_file_system_get_resize_constraint():
    8388608 - 7909522 = 479086 sectors

blktrace reports these numbers of I/Os being performed:
    Read requests   Read bytes
            7,821       71 MiB

So using libparted resize constraint is a bit faster but is still
reading too much data and is really too slow.  Also when testing GParted
using this libparted method against a corrupted FAT32 file system, on
every refresh, one popup dialog is displayed for each error libparted
detects with the file system, each of which needs acknowledgement.
Example popup:

                     Libparted Error
    \DIRNAME\FILENAME.EXT is 107724k, but is has 1920
    clusters (122880k).

                                 [ Cancel ][ Ignore ]

There could be a huge number of such errors in a corrupted file system.
Not really suitable for use by GParted.

Test the performance of mtools' minfo command to report the file system
figures:

    # time minfo -i /dev/sdb2 :: | \
    > egrep 'sector size:|cluster size:|small size:|big size:|free clusters='
    sector size: 512 bytes
    cluster size: 8 sectors
    small size: 0 sectors
    big size: 8388608 sectors
    free clusters=67681

    real    0m0.013s
    user    0m0.004s
    sys     0m0.019s

Free sectors in the file system according to minfo:
    67681 * 8 = 541448 sectors

blktrace reports these numbers of I/Os being performed by minfo:
    Read requests   Read bytes
                1       16 KiB

This matches with minfo just reading information from the BPB (BIOS
Parameter Block) [3] from sector 0 and the FS Information Sector [4]
usually in sector 1.  Note that the free cluster figure reported by
minfo comes from the FS Information Sector because it only reports it
for FAT32 file systems, not for FAT16 file systems.  Scanning the File
Allocation Table (FAT) [5] to count free clusters is exactly what mdir,
without the '-f' (fast) flag, does.  Test the performance of mdir:

    # export MTOOLS_SKIP_CHECK=1
    # time mdir -i /dev/sdb2 ::/ | fgrep 'bytes free'
                            277 221 376 bytes free

    real    0m0.023s
    user    0m0.011s
    sys     0m0.023s

Free sectors in the file system according to mdir:
    277221376 / 512 = 541448 sectors

blktrace reports these number of I/Os being performed by mdir:
    Read requests   Read bytes
                5      448 KiB

So minfo and mdir together provide the needed information and are 2 to 3
orders of magnitude faster because they only read the needed BPB and FAT
data from the drive.  Use these together to read the file system usage.

[1] 61cd0ce778
    lots of stuff and cleanups, including fixing getting used/unused
    space of hfs/hfs+/fat16/fat32

[2] fscons.c
/* FILE:     fscons.c
 * SYNOPSIS: Report libparted's FS resize limits.
 * BUILD:    gcc -o fscons fscons.c -lparted -lparted-fs-resize
 */

int main(int argc, const char *argv[])
{
    PedDevice* dev = NULL;
    PedDisk* tab = NULL;
    PedPartition* ptn = NULL;
    PedFileSystem* fs = NULL;
    PedConstraint* cons = NULL;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: fscons BLOCKDEV\n");
        exit(1);
    }

    dev = ped_device_get(argv[1]);
    if (dev == NULL)
    {
        fprintf(stderr, "ped_device_get(\"%s\") failed\n", argv[1]);
        exit(1);
    }
    printf("dev=%s\n", dev->path);
    printf("sector_size=%ld\n", dev->sector_size);

    tab = ped_disk_new(dev);
    if (tab == NULL)
    {
        fprintf(stderr, "ped_disk_new(dev) failed\n");
        exit(1);
    }

    ptn = ped_disk_get_partition_by_sector(tab, 0);
    if (ptn == NULL)
    {
        fprintf(stderr, "ped_disk_get_partition(tab, 0) failed\n");
        exit(1);
    }

    fs = ped_file_system_open(&ptn->geom);
    if (fs == NULL)
    {
        fprintf(stderr, "ped_file_system_open(&ptn->geom) failed\n");
        exit(1);
    }

    cons = ped_file_system_get_resize_constraint(fs);
    if (cons == NULL)
    {
        fprintf(stderr, "ped_file_system_get_resize_constraint(fs) failed\n");
        exit(1);
    }
    printf("min_size=%ld\n", cons->min_size);
    printf("max_size=%ld\n", cons->max_size);

    ped_constraint_destroy(cons);
    ped_file_system_close(fs);
    ped_disk_destroy(tab);
    ped_device_destroy(dev);

    return 0;
}

[3] Design of the FAT file system, BIOS Parameter Block
    https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BIOS_Parameter_Block

[4] Design of the FAT file system, FS Information Sector
    https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#FS_Information_Sector

[5] Design of the FAT file system, File Allocation Table
    https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#File_Allocation_Table

Bug 569921 - dosfsck -n delays device scan
2019-07-04 10:51:50 -06:00
Goran Vidović a08f317ef7 Update Croatian translation 2019-06-22 17:39:25 +00:00
Balázs Úr bc0677f310 Update Hungarian translation 2019-06-19 21:34:47 +00:00
Daniel Mustieles 6696ab8cec Updated Spanish translation 2019-06-19 12:39:13 +02:00
Piotr Drąg b857ddb5df Update Polish translation 2019-06-16 13:49:30 +02:00
Curtis Gedak 73f9a6f748 Add missing window title to Help Contents dialog (!45)
When GParted is configured with `--disable-doc` the help documentation
is neither built, nor installed.

With this configuration the Help -> Contents menu displays a message
dialog indicating the "Documentation is not available".

On GNOME 3 no title is shown; however, on some other graphic toolkits
/ window managers an unspecified title is shown.

For example on GParted Live with Fluxbox the following is displayed:

                         Unnamed
                         -------

               Documentation is not available

      This build of gparted is configured without documentation.
      Documentation is available at the project web site.
      https://gparted.org

                           OK

To address the unspecified title on non-GNOME 3 graphic toolkits, add
a title that works with and without GNOME 3.

Closes !45 - Add missing window title to Help Contents dialog
2019-06-12 15:26:54 +00:00
Mike Fleetwood 1d8cbd0125 Add missing Device.h include into GParted_Core and Win_GParted
The files GParted_Core.h, GParted_Core.cc and Win_GParted.cc all use the
Device type but don't include Device.h for it's definition.  Include it.
2019-06-11 15:55:02 +00:00
Mike Fleetwood 1ed8d909fc Replace partition boundary trimming with bug error messages (#48)
All the dialogs which compose new or modified partition boundaries
create those partitions within the boundaries of the device.  Therefore
trimming the partition boundaries to device boundaries never happens.
So replace this trimming with bug error reports.

Also add bug prefixes to the other error messages in
GParted_Core::valid_partition() too.

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Mike Fleetwood e3b0558f62 White space layout update in snap_to_mebibyte/cylinder() (#48)
The previous commit moved the code from GParted_Core to
Dialog_Base_Partition class without making a single formatting change to
ensure the code was guaranteed to work the same within that larger
commit.  Now reformat the code to current layout standards.  Making it a
separate commit simplifies the effort for both changes and improves
bisectability.

Additionally to be sure there were no code changes,
Dialog_Base_Partition.cc was compiled to assembler code with and without
this change applied and the resultant assembler code compared.  There
were no differences in the generated assembler code.

Start with the make generated g++ command for compiling
Dialog_Base_Partition.o; (1) remove the '-g' flag as inserted debugging
directives do differ; and (2) replace '-c -o Dialog_Base_Partition.o'
with '-S -o Dialog_Base_Partition.s' to produce assembler output instead
of object code.

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Mike Fleetwood 7c94b7d920 Snap partition boundaries before dialogs update FS usage (#48)
Move snap_to_*() method calls from the point when all operations are
added to the list, to earlier when Resize/Move, Paste (into new) and
Create New dialogs are composing the new partition objects.  In
particular for the Resize/Move operation, to just before updating the
file system usage.

This change finally resolves this bug.

Because of the dialog call chains into Dialog_Base_Partition,
snap_to_alignment() must be added into:
* Dialog_Base_Partition::prepare_new_partition() for the Resize/Move and
  Paste (into new) dialogs; and
* Dialog_Partition_New::Get_New_Partition() for the Create New dialog.

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Mike Fleetwood 3222c8dd1a Pass the current device down to Dialog_Base_Partition class (#48)
The current device has to be passed to the dialog constructors and then
on to the Dialog_Base_Constructor.  Note that the Dialog_Partition_New
constructor is already passed the current device, however it still needs
to pass it on to Dialog_Base_Constructor.

This is ready so that snap_to_*() methods can access the current device
when they are called from within these dialogs.

* Pass Parameter to Base Class Constructor while creating Derived class
  Object
  https://stackoverflow.com/questions/16585856/pass-parameter-to-base-class-constructor-while-creating-derived-class-object

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Mike Fleetwood 4101b0961b Update file system usage last in prepare_new_partition() (#48)
Move setting of the new_partition object file system usage to after
everything else, specifically after free_space_before and strict_start.
This is because snap_to_*() use free_space_before and strict_start and
snap_to_alignment() is going to be called before the file system usage
is updated to avoid the error in this bug report.

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Mike Fleetwood 14aa9276d4 Remove unused error reporting from snap_to_*() (#48)
None of the snap_to_*() methods report any errors so remove the unused
error parameter and return value.

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Mike Fleetwood 406beaaed0 Separate partition alignment from validation (#48)
PATCHSET OVERVIEW

A user had 2 adjacent partitions which were aligned to multiples of
33553920 bytes (32 MiB - 512 bytes), not MiB or cylinders.  As far as
GParted is concerned this is not aligned.  The second partition
contained closed LUKS encrypted data.  Recreate this setup with:

    # truncate -s 200G /tmp/disk.img
    # losetup -f --show /tmp/disk.img
    /dev/loop0
    # sfdisk -u S /dev/loop0 << EOF
    65535 2162655 83
    2228190 78904140 83
    EOF
    # partprobe /dev/loop0
    # echo -n badpassword | cryptsetup luksFormat /dev/loop0p2 -

When trying to move the second LUKS encrypted partition to the right by
any amount, with the default MiB alignment, GParted displays this error
dialog and fails to even queue the operation:

    Could not add this operation to the list
    A partition with used sectors (78907392) greater than its
    length (78905344) is not valid
    [                       OK                               ]

Overview of the steps involved:

1. The Resize/Move dialog composed a new partition to start a whole
   multiple of MiB after the end of the previous non-aligned partition.
   The new partition also had it's size increased to a whole multiple of
   MiB, to 78907392 sectors (38529 MiB) which was 1.59 MiB larger than
   before.  Neither the start or end of the new partition are aligned at
   this point.

2. Win_GParted::activate_resize() applied the change back to the closed
   LUKS partition object, additionally making the used sectors equal to
   the partition size.
   (To match the fact that when opened the LUKS mapping it will
   automatically fill the new larger partition size).

3. GParted_Core::snap_to_mebibyte() then aligned the partition start and
   end to whole MiB boundaries, reducing the partition size in the
   process to 78905344 (38528 MiB).

4. GParted_Core::snap_to_alignment() reported the error saying that it
   couldn't add the operation to the list because it was invalid to have
   the file system used sectors larger than the partition size.

Fix this by having the snap to alignment adjustments applied before the
dialogs update any associated file system usage.  Specifically the
Resize/Move, Paste (into new) and Create New dialogs as these are the
only ones which either create or modify partition boundaries.
Validation done by snap_to_alignment() will continue to occur at the
current point when the operation is added to the list.

THIS COMMIT

snap_to_alignment() is doing two different jobs, it is (1) optionally
adjusting the new partition boundaries for MiB or Cylinder alignment;
and (2) checking that the partition boundaries and file system usage are
valid.

Split those into two different functions (1) snap_to_alignment() and
(2) valid_partition().  For now valid_partition() still calls
snap_to_alignment() so there is no functional change with this commit.

Closes #48 - Error when moving locked LUKS-encrypted partition
2019-06-11 15:55:02 +00:00
Daniel Șerbănescu 45d046fc8b Update Romanian translation 2019-06-09 09:43:48 +00:00
Wolfgang Stöggl 7096807585 Update German translation 2019-06-06 06:48:56 +00:00
Balázs Úr a0d2e5a23b Update Hungarian translation 2019-06-03 19:46:54 +00:00
Félix Piédallu cdba5cee35 Fix test (dentry->d_name is invalidated by closedir...) (!41)
We have to copy the dentry->d_name before calling closedir().  If not,
the string points to nothing and the test fails (It does not fail all
the time, but only by chance).

Confirmed using valgrind.  Selected output from running the unit test
under valgrind:

  $ valgrind --track-origins=yes ./test_blockSpecial
  ==25110== Memcheck, a memory error detector
  ...
  ==25110== Command: ./test_BlockSpecial
  ==25110==
  Running main() from src/gtest_main.cc
  [==========] Running 26 tests from 1 test case.
  [----------] Global test environment set-up.
  [----------] 26 tests from BlockSpecialTest
  ...
  [ RUN      ] BlockSpecialTest.NamedBlockSpecialObjectBySymlinkMatches
  ==25110== Invalid read of size 1
  ==25110==    at 0x4C2C9B2: strlen (vg_replace_strmem.c:458)
  ==25110==    by 0x40E7C4: length (char_traits.h:259)
  ==25110==    by 0x40E7C4: append (basic_string.h:1009)
  ==25110==    by 0x40E7C4: operator+<char, std::char_traits<char>, std::allocator<char> > (basic_string.h:2468)
  ==25110==    by 0x40E7C4: get_link_name (test_BlockSpecial.cc:156)
  ==25110==    by 0x40E7C4: GParted::BlockSpecialTest_NamedBlockSpecialObjectBySymlinkMatches_Test::TestBody() (test_BlockSpecial.cc:247)
  ...
  =25110==  Address 0x1231ea93 is 115 bytes inside a block of size 32,816 free'd
  ==25110==    at 0x4C2ACBD: free (vg_replace_malloc.c:530)
  ==25110==    by 0x9F773AC: closedir (in /usr/lib64/libc-2.17.so)
  ==25110==    by 0x40E7AC: get_link_name (test_BlockSpecial.cc:153)
  ==25110==    by 0x40E7AC: GParted::BlockSpecialTest_NamedBlockSpecialObjectBySymlinkMatches_Test::TestBody() (test_BlockSpecial.cc:247)
  ...
  ==25110==  Block was alloc'd at
  ==25110==    at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
  ==25110==    by 0x9F77280: __alloc_dir (in /usr/lib64/libc-2.17.so)
  ==25110==    by 0x40E746: get_link_name (test_BlockSpecial.cc:134)
  ==25110==    by 0x40E746: GParted::BlockSpecialTest_NamedBlockSpecialObjectBySymlinkMatches_Test::TestBody() (test_BlockSpecial.cc:247)
  ...
  ==25110== Invalid read of size 1
  ==25110==    at 0x4C2E220: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1022)
  ==25110==    by 0x953A997: std::string::append(char const*, unsigned long) (in /usr/lib64/libstdc++.so.6.0.19)
  ==25110==    by 0x40E7D2: append (basic_string.h:1009)
  ==25110==    by 0x40E7D2: operator+<char, std::char_traits<char>, std::allocator<char> > (basic_string.h:2468)
  ==25110==    by 0x40E7D2: get_link_name (test_BlockSpecial.cc:156)
  ==25110==    by 0x40E7D2: GParted::BlockSpecialTest_NamedBlockSpecialObjectBySymlinkMatches_Test::TestBody() (test_BlockSpecial.cc:247)
  ...
  ==25110==  Address 0x1231ea93 is 115 bytes inside a block of size 32,816 free'd
  ==25110==    at 0x4C2ACBD: free (vg_replace_malloc.c:530)
  ==25110==    by 0x9F773AC: closedir (in /usr/lib64/libc-2.17.so)
  ==25110==    by 0x40E7AC: get_link_name (test_BlockSpecial.cc:153)
  ==25110==    by 0x40E7AC: GParted::BlockSpecialTest_NamedBlockSpecialObjectBySymlinkMatches_Test::TestBody() (test_BlockSpecial.cc:247)
  ...
  ==25110==  Block was alloc'd at
  ==25110==    at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
  ==25110==    by 0x9F77280: __alloc_dir (in /usr/lib64/libc-2.17.so)
  ==25110==    by 0x40E746: get_link_name (test_BlockSpecial.cc:134)
  ==25110==    by 0x40E746: GParted::BlockSpecialTest_NamedBlockSpecialObjectBySymlinkMatches_Test::TestBody() (test_BlockSpecial.cc:247)
  ...
  [       OK ] BlockSpecialTest.NamedBlockSpecialObjectBySymlinkMatches (50 ms)

Selected lines from test_BlockSpecial.cc:

  132  static std::string get_link_name()
  133  {
  134          DIR * dir = opendir( "/dev/disk/by-id" );
  ...
  141          bool found = false;
  142          struct dirent * dentry;
  143          // Silence GCC [-Wparentheses] warning with double parentheses
  144          while ( ( dentry = readdir( dir ) ) )
  145          {
  146                  if ( strcmp( dentry->d_name, "." )  != 0 &&
  147                       strcmp( dentry->d_name, ". " ) != 0    )
  148                  {
  149                          found = true;
  150                          break;
  151                  }
  152          }
  153          closedir( dir );
  154
  155          if ( found )
  156                  return std::string( "/dev/disk/by-id/" ) + dentry->d_name;

So the memory referred to by dentry was allocated on line 134, freed on
153 and accessed after freed on 156.

Closes !41 - Fix test (dentry->d_name is invalidated by closedir...)
2019-05-31 19:32:52 +01:00
Curtis Gedak 0dedf8defe Fix link typo in French translation of GParted help manual 2019-05-29 11:36:03 -06:00
Curtis Gedak e04b928423 Append -git to version for continuing development 2019-05-29 10:21:07 -06:00
Curtis Gedak b5f1d5d5fe ========== gparted-1.0.0 ========== 2019-05-29 09:54:20 -06:00
Curtis Gedak 6c9194869c Update copyright years 2019-05-29 09:46:10 -06:00
Claude Paroz 7186e7026f Update French translation 2019-05-28 18:05:02 +00:00
Mike Fleetwood 5e77368daa Fix reading NTFS usage after resize (#57)
After an NTFS file system has been resized the command GParted currently
uses to read the file system usage fails like this:

    # ntfsinfo --mft /dev/sdb1
    Volume is scheduled for check.
    Please boot into Windows TWICE, or use the 'force' option.
    NOTE: If you had not scheduled check and last time accessed this volume
    using ntfsmount and shutdown system properly, then init scripts in your
    distribution are broken. Please report to your distribution developers
    (NOT to us!) that init scripts kill ntfsmount or mount.ntfs-fuse during
    shutdown instead of proper umount.
    Failed to open '/dev/sdb1'.

Fix by added the '--force' flag as described in the error message.

Closes #57 - NTFS Resize results in Partition Information Warning on
             Refresh
2019-05-28 16:01:25 +00:00
Mike Fleetwood fbcf4b56bb Report errors correctly on failure to read NTFS usage (#57)
GParted uses ntfsinfo to read the NTFS file system usage.  However when
ntfsinfo fails with a non-zero exit status GParted reports stdout twice,
rather than stdout and stderr.  Correct this.

Closes #57 - NTFS Resize results in Partition Information Warning on
             Refresh
2019-05-28 16:01:25 +00:00
Anders Jonsson e9d73bbf1c Update Swedish translation 2019-05-26 19:42:51 +00:00
Anders Jonsson c6fe455a3b Update Swedish translation 2019-05-26 17:48:42 +00:00
Trần Ngọc Quân 1d806939a4 Updated Vietnamese translation
Signed-off-by: Trần Ngọc Quân <vnwildman@gmail.com>
2019-05-25 15:30:17 +07:00