Commit Graph

527 Commits

Author SHA1 Message Date
Mike Fleetwood 317114ffcb Populate LUKS partition usage (#760080)
Populate the used, unused and unallocated figures in the Partition
object for a LUKS formatted partition.  See comment in
luks::set_used_sectors() for the rational of what is used, unused and
unallocated.

As that rational mentions, a LUKS header does not store the size of the
encrypted data and is assumed to extend to the end of the partition by
the tools which start the mapping.

An underlying block device of 128 MiB (131072 KiB).
    # sfdisk -s /dev/sde
    131072

An active LUKS mapping at offset 2 MiB (4096 512-byte sectors) and
length 126 MiB (129024 KiB, 258048 512-byte sectors).
    # sfdisk -s /dev/mapper/sde_crypt
    129024
    # cryptsetup status sde_crypt
    /dev/mapper/sde_crypt is active.
      type:  LUKS1
      cipher:  aes-cbc-essiv:sha256
      keysize: 256 bits
      device:  /dev/sde
      offset:  4096 sectors
      size:    258048 sectors
      mode:    read/write

No size/length reported when dumping the LUKS header, just (payload)
offset.
    # cryptsetup luksDump /dev/sde
    LUKS header information for /dev/sde

    Version:        1
    Cipher name:    aes
    Cipher mode:    cbc-essiv:sha256
    Hash spec:      sha1
    Payload offset: 4096
    MK bits:        256
    MK digest:      7f fb ba 40 7e ba e4 3b 2f c6 d0 93 7b f7 05 49 7b 72 d4 ad
    MK salt:        4a 5b 54 f9 7b 67 af 6e ef 16 31 0a fe d9 7e 5f
                    c3 66 dc 8a ed e0 07 f4 45 c3 7c 1a 8d 7d ac f4
    MK iterations:  37750
    UUID:           0a337705-434a-4994-a842-5b4351cb3778
    ...

Shrink the LUKS mapping to 64 MiB (65536 KiB, 131072 512-byte sectors).
    # cryptsetup resize --size 131072 sde_crypt
    # sfdisk -s /dev/mapper/sde_crypt
    65536
    # cryptsetup status sde_crypt
    /dev/mapper/sde_crypt is active.
      type:  LUKS1
      cipher:  aes-cbc-essiv:sha256
      keysize: 256 bits
      device:  /dev/sde
      offset:  4096 sectors
      size:    131072 sectors
      mode:    read/write

Stop and start the LUKS mapping.
    # cryptsetup luksClose sde_crypt
    # cryptsetup luksOpen /dev/sde sde_crypt

The size of the LUKS mapping is back to 126 MiB (129024 KiB, 258048
512-byte sectors), extending to the end of the partition.
    # sfdisk -s /dev/mapper/sde_crypt
    129024
    # cryptsetup status sde_crypt
    /dev/mapper/sde_crypt is active.
      type:  LUKS1
      cipher:  aes-cbc-essiv:sha256
      keysize: 256 bits
      device:  /dev/sde
      offset:  4096 sectors
      size:    258048 sectors
      mode:    read/write

Bug 760080 - Implement read-only LUKS support
2016-01-29 13:41:40 -07:00
Mike Fleetwood 317e444056 Add loading of LUKS mapping offset and length (#760080)
Also load the starting offset and length of the active dm-crypt mapping
into the LUKS_Info module from the dmsetup output.  This provides the
location and size of the encrypted data within the underlying block
device.

Note that dmsetup reports in units of 512 bytes sectors [1], the GParted
LUKS_Info module uses bytes and GParted Partition objects work in device
sector size units.  However the actual sector size of a dm-crypt mapping
[2] is the same as that of the underlying block device [3].

    # modprobe scsi_debug dev_size_mb=128 sector_size=4096
    # fgrep scsi_debug /sys/block/*/device/model
    /sys/block/sdd/device/model:scsi_debug
    # parted /dev/sde print
    Error: /dev/sde: unrecognised disk label
    Model: Linux scsi_debug (scsi)
    Disk /dev/sde: 134MB
[3] Sector size (logical/physical): 4096B/4096B
    Partition Table: unknown

    # cryptsetup luksFormat /dev/sde
    # cryptsetup luksOpen /dev/sde sde_crypt
    # parted /dev/mapper/sde_crypt print
    Error: /dev/mapper/sde_crypt: unrecognised disk label
    Model: Linux device-mapper (crypt) (dm)
    Disk /dev/mapper/sde_crypt: 132MB
[2] Sector size (logical/physical): 4096B/4096B
    Partition Table: unknown

    # cryptsetup status sde_crypt
    /dev/mapper/sde_crypt is active.
      type:  LUKS1
      cipher:  aes-cbc-essiv:sha256
      keysize: 256 bits
      device:  /dev/sde
      offset:  4096 sectors
      size:    258048 sectors
      mode:    read/write
    # dmsetup table --target crypt
    ...
    sde_crypt: 0 258048 crypt aes-cbc-essiv:sha256 0000000000000000000000000000000000000000000000000000000000000000 0 8:64 4096

[1] Both cryptsetup and dmsetup report the offset as 4096 and the size/
length as 258048.  128 MiB / (4096+258048) = 512 byte units, even on a
4096 byte sector size device.

Update debugging of LUKS to this:

    # ./gpartedbin
    ======================
    libparted : 2.4
    ======================
    DEBUG: /dev/sdb5: LUKS closed
    DEBUG: /dev/sdb6: LUKS open mapping /dev/mapper/sdb6_crypt, offset=2097152, length=534773760
    /dev/sde: unrecognised disk label
    DEBUG: /dev/sde: LUKS open mapping /dev/mapper/sde_crypt, offset=2097152, length=132120576

Bug 760080 - Implement read-only LUKS support
2016-01-29 13:41:40 -07:00
Mike Fleetwood 070d734e57 Add busy detection of LUKS mapping (#760080)
Provide a minimal implementation of a luks file system class which only
does busy detection.

NOTE:
For now, read-only LUKS support, a LUKS partition will be busy when a
dm-crypt mapping exists.  Later when read-write LUKS support is added
GParted will need to look at the busy status of the encrypted file
system within the open LUKS partition and map LUKS partition busy status
to encryption being open or closed.

Bug 760080 - Implement read-only LUKS support
2016-01-29 13:41:40 -07:00
Mike Fleetwood b77a6be76b Add initial loading of LUKS mapping details (#760080)
Load basic details of active Device-mapper encryption mappings from the
kernel.  Use dmsetup active targets.

    # cryptsetup luksFormat /dev/sdb5
    # cryptsetup luksFormat /dev/sdb6
    # cryptsetup luksOpen /dev/sdb6 sdb6_crypt
    # ls -l /dev/mapper/sdb6_crypt /dev/dm-0
    lrwxrwxrwx. 1 root root 7 Nov 15 09:03 /dev/mapper/sdb6_crypt -> ../dm-0
    brw-rw----. 1 root disk 253, 0 Nov 15 09:03 /dev/dm-0
    # ls -l /dev/sdb6
    brw-rw----. 1 root disk 8, 22 Nov 15 09:02 /dev/sdb6
    # dmsetup table --target crypt
    sdb6_crypt: 0 1044480 crypt aes-cbc-essiv:sha256 0000000000000000000000000000000000000000000000000000000000000000 0 8:22 4096

So far just load the mapping name and underlying block device reference
(path or major, minor pair).

Note that all supported kernels appear to report the underlying block
device as major, minor pair in the dmsetup output.  Underlying block
device paths are added to the cache when found during a search to avoid
stat(2) call on subsequent searches for the same path.

Prints debugging to show results, like this:

    # ./gpartedbin
    ======================
    libparted : 2.4
    ======================
    DEBUG: /dev/sdb5: LUKS closed
    DEBUG: /dev/sdb6: LUKS open mapping /dev/mapper/sdb6_crypt

Bug 760080 - Implement read-only LUKS support
2016-01-29 13:41:40 -07:00
Mike Fleetwood 1b55dfad5b Move DEV_MAPPER_PATH from DMRaid.h to Utils.h (#760080)
Renamed from DEV_MAP_PATH to DEV_MAPPER_PATH.  Moved so that the
constant is logically intended for use outside of the DMRaid class.

Also specifically make the string constant have external linkage, rather
than the default internal (static) linkage for constants, so that there
is only one copy of the variable in the program, rather than one copy in
each compilation unit which included DMRaid.h.  Namely DMRaid.cc and
GParted_Core.cc.

References:
[1] Proper way to do const std::string in a header file?
    http://stackoverflow.com/questions/10201880/proper-way-to-do-const-stdstring-in-a-header-file
[2] What is external linkage and internal linkage in C++
    http://stackoverflow.com/questions/1358400/what-is-external-linkage-and-internal-linkage-in-c/1358796#1358796

Bug 760080 - Implement read-only LUKS support
2016-01-29 13:41:40 -07:00
Mike Fleetwood cd64d6503b Remove unused Partition(path) constructor
History:

1) The constructor was added by commit:

    6d8b169e73
    2006-03-14 21:37:47
    changed the way devices and partitions store their devicepaths.  Instead of

2) Removed from most of the file system specific ::Copy() methods by
   commit:

    ad9f2126e7
    2006-03-19 15:30:20
    fixed issues with copying (see also #335004) cleanups + added FIXME added

3) Removed from GParted_Core::copy() method by commit:

    7bb7e8a84f
    2006-05-23 22:17:34
    Use ped_device_read and ped_device_write instead of 'dd' to copy

4) Finally removed from the last place in xfs::Copy() method by commit:

    e414b71b73
    2012-01-11 19:49:13
    Update xfs resize and copy to use new helper functions

The Partition(path) constructor is no longer used.  Remove.
2016-01-26 10:11:36 -07:00
Mike Fleetwood 561e2203d5 Add virtual qualifier to derived Operation class destructors
When a base class destructor is virtual, derived class destructors are
also virtual [1] even if they don't have the virtual qualifier.

As the Operation destructor is virtual, derived Operation* classes
destructors are virtual too.  Add virtual qualifier just to reflect what
the C++ language mandates the compiler implement.

[1] Derived class with non-virtual destructor
    http://stackoverflow.com/questions/7403883/derived-class-with-non-virtual-destructor
2016-01-26 10:11:36 -07:00
Mike Fleetwood 24fa553385 Remove unnecessary sector_size parameter from Get_New_Partition methods
The sector_size parameter is unnecessary as the value can be retrieved
from the sector size of the selected Partition object on which the
create new, copy & paste or resize/move operation is being performed.

For the create new and resize/move operations it is trivial as the
existing unallocated or in use Partition object on which the operation
is being perform already contains the correct sector size.  For the copy
& paste operation, which can copy across disk devices of different
sector sizes, we merely have to use the sector size of the existing
selected (destination) Partition object rather than copied (source)
Partition object.  Hence these relevant lines in the new code:

    Dialog_Partition_Copy::set_data(selected_partition, copied_partition)
        new_partition = copied_partition.clone();
        ...
        new_partition->sector_size = selected_partition.sector_size;
2016-01-26 10:11:35 -07:00
Mike Fleetwood 1a4cefb960 Initialise all struct FS members
The struct FS constructor initialised every member *except* filesystem
and busy.  Then in *most* cases after declaring struct FS, assignments
followed like this:
    FS fs;
    fs.filesystem = FS_BTRFS;
    fs.busy       = FS::GPARTED;
But member busy wasn't always initialised.

Add initialisation of members filesystem and busy to the struct FS
constructor.  Specify optional parameter to the constructor to set the
filesystem member, or when left off filesystem is initialised to
FS_UNKNOWN.
2016-01-26 10:11:35 -07:00
Mike Fleetwood 320e166c03 Implement and use virtual Partition copy constructor clone() (#759726)
Final step for full polymorphic handling of Partition objects is to
implement a virtual copy constructor.  C++ doesn't directly support
virtual copy constructors, so instead use the virtual copy constructor
idiom [1].  (Just a virtual method called clone() which is implemented
in every polymorphic class and creates a clone of the current object and
returns a pointer to it).

Then replace all calls to the (monomorphic) Partition object copy
constructor throughout the code, except in the clone() implementation
itself, with calls to the new virtual clone() method "virtual copy
constructor".

Also have to make the Partition destructor virtual too [2][3] so that
the derived class destructor is called when deleting using a base class
pointer.  C++ supports this directly.

[1] Wikibooks: More C++ Idioms / Virtual Constructor
    https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor

[2] When to use virtual destructors?
    http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors

[3] Virtuality
    Guideline #4: A base class destructor should be either public and
    virtual, or protected and nonvirtual
    http://www.gotw.ca/publications/mill18.htm

Bug 759726 - Implement Partition object polymorphism

SQUASH: When first using pointers to Partition and calling delete
2016-01-26 10:11:35 -07:00
Mike Fleetwood 656e1709ff Replace all Partition object copy assignment (#759726)
Copy assignment of Partition objects is now only performed in a few
places in the Operation and OperationResizeMove classes when updating
the displayed PartitionVector.  (From Refresh_Visual() when each
operation is visually applied to the display_partitions vector; the
new_partition from the operation is copy assigned over the top of the
relevant existing partition in the display_partitions vector).

In general polymorphic copy assignment is complicated [1], and is now
unnecessary given the above limited use.  All that is needed is a way to
polymorphically replace one Partition object with another in a
PartitionVector.

First, prevent further use of Partition object copy assignment by
providing a private declaration and no implementation, so the compiler
enforces this.  Second implement and use PartitionVector method
replace_at() which replaces a pointer to one Partition object with
another at the specified index in the PartitionVector.

[1] The Assignment Operator Revisited
    [Section:] Virtual assignment
    http://icu-project.org/docs/papers/cpp_report/the_assignment_operator_revisited.html

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 4a6cbcd0f1 Use pointer to Partition in Dialog_Base_Partition and derived classes (#759726)
Now use a pointer to the Partition object in Dialog_Base_Partition class
and derived classes, Dialog_Partition_{Copy,New,Resize_Move}.  This is
equivalent to how the Partition objects are managed in the Operation and
derived classes.

The Partition object is allocated and copy constructed in each derived
classes' set_data() method, called from each constructor and deallocated
in the destructors.  Considering the remaining Big 3, these classes are
never copy constructed or copy assigned so provide private definitions
and no implementations so the compiler enforces this.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood ea8ab702f7 Change copied_partition into a pointer (#759726)
Change Win_GParted::copied_partition from Partition object which is
copied by value into a pointer to a Partition object object which is
allocated, copy constructed and deleted.  Required as part of the
polymorphic implementation of Partitions.

As before when managing the lifetime of pointers to objects in a class
the Big 3 of destructor, copy constructor and copy assignment operator
need to be considered.  A destructor is added to finally delete
copied_partition.  A single Win_GParted object is only ever created and
destroyed in main().  The class is never copy constructed or copy
assigned.  Make the compiler enforce this with private declarations and
no implementations.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood b516b1093c Use pointers to Partitions in Operation classes (#759726)
Operation classes now internally use pointers to Partition objects and
take on management of their lifetimes.  As before, with the
PartitionVector class, when storing pointers in a class the Big 3 of
destructor, copy constructor and copy assignment operator also have to
be considered.

First, all the Partition objects are allocated in the derived Operation*
class parameterised constructors and freed in the associated
destructors.  However the Operation classes are never copy constructed
or copy assigned; they are only ever created and destroyed.  Only
pointers to the derived Operations are copied into the vector of pending
operations.  Therefore the copy construtor and copy assignment operator
aren't needed.  To enforce this provide inaccessible private
declarations without any implementation so that the compiler will
enforce this [1][2].

This example code fragment:
 1  OperationCheck o1( device, partition );
 2  OperationCheck o2 = o1;
 3  o2 = o1;
Does these OperationCheck calls:
 1  Implemented parameterised construtor,
 2  Disallowed copy constructor,
 3  Disallowed copy assignment

Trying to compile the above code would fail with errors like these:
    ../include/OperationCheck.h: In member function 'void GParted::Win_GParted::activate_check()':
    ../include/OperationCheck.h:36:2: error: 'GParted::OperationCheck::OperationCheck(const GParted::OperationCheck&)' is private
      OperationCheck( const OperationCheck & src );              // Not implemented copy constructor
      ^
    test.cc:2:21: error: within this context
      OperationCheck o2 = o1;
                          ^

    ../include/OperationCheck.h:37:19: error: 'GParted::OperationCheck& GParted::OperationCheck::operator=(const GParted::OperationCheck&)' is private
      OperationCheck & operator=( const OperationCheck & rhs );  // Not implemented copy assignment operator
                       ^
    test.cc:3:4: error: within this context
      o2 = o1;
         ^

[1] Disable copy constructor
    http://stackoverflow.com/questions/6077143/disable-copy-constructor
[2] Disable compiler-generated copy-assignment operator [duplicate]
    http://stackoverflow.com/questions/7823845/disable-compiler-generated-copy-assignment-operator

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 6fd37c0745 Protect partition members within Operation classes (#759726)
The Operation classes contain partition objects which are copied by
value.  Need to replace these with pointers to Partition objects instead
and manage their lifetimes so that they can be used polymorphically.

First step is to protect the partition members partition_new,
partition_original, and for OperationCopy class only, partition_copied
within the Operation classes and provide accessor methods.

get_partition_new() and get_partition_original() accessors are
implemented in the Operation base class so all derived classes get an
implementation.  get_partition_new() is also virtual so that
OperationCheck and OperationDelete can override the implementation and
assert that they don't use partition_new.  get_partition_copied() is
provided for the OperationCopy class only so can only be accessed via an
OperationCopy type variable.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 504a2d8393 Remove copy constructing add item methods from PartitionVector (#759726)
Remove PartitionVector push_back() and insert() methods which copy
construct Partitions objects into the vector.  All the code has already
been changed to dynamically allocate Partition objects and use the
adoption variants of these methods named, push_back_adopt() and
insert_adopt().  Remove the no longer used methods.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 2a2a99b2bf Consolidate down to a single insert_unallocated() implementation (#759726)
GParted_Core and Operation classes both have an insert_unallocated()
method which do the same thing with very nearly identical code.  Both
methods insert unallocated partitions into the vector of partitions
within the specified range of sectors to fill in any gaps larger than
1 MiB.  The only difference was how the two methods got the device path;
the GParted_Core class method got it via a parameter and the Operation
class method got it by calling get_path() on its device member variable.
The GParted_Core insert_unallocated() method gets called during device
scanning and the Operation one gets called when constructing the visual
for a pending operation.

Consolidate down to a single insert_unallocated() implementation by
making the Operation class method call the GParted_Core class method.
Make the GParted_Core class method static and public so that it can be
called using the class name from outside the class.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood fdbd86f1ea Add adoption methods for adding items into a PartitionVector (#759726)
The current code uses push_back() and insert() to copy Partition objects
into the vector of pointers.  This has a few issues:
1) Unnecessary copying of Partition objects;
2) Hides the nature of the PartitionVector class as a manager of
   pointers to Partition objects by providing copy semantics to add
   items.  It is generally better to be explicit;
3) C++ doesn't provide polymorphic copy construction directly, but this
   is easily worked around by following the Virtual Constructor idiom
   [1], which would allow PartitionLUKS derived class objects to be
   copied into the vector.

Add push_back_adopt() and insert_adopt() methods which add a pointer to
a Partition object into the PartitionVector adopting ownership.

[1] Wikibooks: More C++ Idioms / Virtual Constructor
    https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 06b8a3a14a Use pointers to Partitions in PartitionVector class (#759726)
The PartitionVector class is now internally using pointers to Partition
objects and taking on management of their lifetimes.  It therefore has
to implement the Big 3: destructor, copy constructor and copy assignment
operator [1][2].  This is because the implicitly-defined copy
constructor and assignment operator perform memberwise "shallow copying"
and the destructor does nothing.  This not correct for classes which
contain non-class types such as raw pointers.

The semantics of the interface still copies each Partition object into
the PartitionVector when they are added with push_back() and insert().

Note that a PartitionVector object is explicitly copy assigned in
Win_GParted::Refresh_Visual().  They are also implicitly copied when
(1) the implementing vector is resized larger to allow it to hold more
pointers to Partition objects than it previously had capacity for; and
(2) a Partition object is copied including the logicals PartitionVector
member.

[1] The rule of three/five/zero
    http://en.cppreference.com/w/cpp/language/rule_of_three
[2] Rule of Three
    https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 48d898ebfd Include Partition.h header everywhere it's used
Lots of files which use the Partition class relied on the declaration
being included via other header files.  This is bad practice.

Add #include "Partition.h" into every file which uses the Partition
class which doesn't already include it.  Header file #include guards are
specifically to allow this.
2016-01-26 10:11:35 -07:00
Mike Fleetwood fae909897e Use PartitionVector class throughout the code (#759726)
Replace all occurrences of std::vector<Partition> with PartitionVector.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:35 -07:00
Mike Fleetwood 81337141d7 Stop returning vector of partitions from Dialog_Rescue_Data class (#759726)
get_partitions() method was returning a vector of partitions.  However
the calling code only needed to know whether any partitions were found
or not.  Replace with found_partitions() method reporting the needed
boolean.

Now use of std::vector<Partition> partitions is hidden within the
Dialog_Rescue_Data class implementation.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:34 -07:00
Mike Fleetwood fa98273445 Create PartitionVector class (#759726)
Just creates PartitionVector class and includes it in partition.h so
that it is built and validated by the compiler.  Not used anywhere yet.

Implementation strategy is to create a PartitionLUKS class derived from
the Partition class.  This implies polymorphism of Partition objects,
which in C++ requires using pointers and references to objects, and not
using objects directly.  (See C++ object slicing).  Later this
PartitionVector class will be modified to use pointers to Partition
objects and act as the owner of the pointed to Partition objects.

Bug 759726 - Implement Partition object polymorphism
2016-01-26 10:11:34 -07:00
Phillip Susi ae434579e1 Display progress for e2fsck (#467925)
Parse output and update progress bar.

Bug 467925 - gparted: add progress bar during operation
2015-12-14 10:42:04 -07:00
Phillip Susi baea186138 Display progress for mke2fs (#467925)
Bug 467925 - gparted: add progress bar during operation
2015-12-14 10:42:04 -07:00
Phillip Susi 57b028bb8e Display progress during resize (#467925)
Capture and parse the progress reports of ntfsresize and resize2fs and
update the dialog progress bar.

Bug 467925 - gparted: add progress bar during operation
2015-12-14 10:42:04 -07:00
Mike Fleetwood 2c4df87a2c Return reference from Get_New_Partition() (#757671)
Return newly constructed partition object by reference rather than by
copy from the Copy, Resize/Move and New dialog classes.  This is another
case of stopping copying partition objects in preparation for using
polymorphic Partition objects.  In C++ polymorphism has to use pass by
pointer and reference and not pass by value, copying, to avoid object
slicing.

The returned reference to the partition is only valid until the dialog
object containing the new_partition member is destroyed.  This is okay
because in all three cases the returned referenced partition is copied
into a context with new lifetime expectations before the dialog object
is destroyed.

Case 1: GParted_Core::activate_paste()
    Referenced new_partition is copied in the OperationCopy constructor
    before the dialog object goes out of scope.

    Operation * operation = new OperationCopy( ...,
                                               dialog.Get_New_Partition( ... ),
                                               ... );

Case 2: GParted_Core::activate_new()
    Referenced new_partition is copied in the OperationCreate
    constructor before the dialog object goes out of scope.

    Operation * operation = new OperationCreate( ...,
                                                 dialog.Get_New_Partition( ... ) );

Case 3: GParted_Core::activate_resize()
    Temporary partition object is copied from the referenced
    new_partition before the dialog object goes out of scope.

    Partition part_temp = dialog.Get_New_Partition( ... );

Bug 757671 - Rework Dialog_Partition_New::Get_New_Partition() a bit
2015-11-11 10:12:18 -07:00
Mike Fleetwood 451c2eac43 Rename parameter to selected_partition in Dialog_Partition_New methods (#757671)
This is just to make the parameter name in the Dialog_Partition_New
constructor and set_data() method match the name of the equivalent
parameter in the Dialog_Partition_Copy and Dialog_Partition_Resize_Move
classes.  (All three classes inherit from Dialog_Base_Partition and have
similar interfaces).

Bug 757671 - Rework Dialog_Partition_New::Get_New_Partition() a bit
2015-11-11 10:12:18 -07:00
Mike Fleetwood bab1109d3d Ensure SWRaid_Info cache is loaded at least once (#756829)
Automatically load the cache of SWRaid information for the first time if
any of the querying methods are called before the first explicit
load_cache() call.  Means we can't accidentally use the class and
incorrectly find no SWRaid members when they do exist.

Bug 756829 - SWRaid member detection enhancements
2015-11-02 10:03:45 -07:00
Mike Fleetwood f6c2f00df7 Populate member mount point with SWRaid array device (#756829)
Busy file systems are accessed via a mount point, LVM Physical Volumes
are activated via the Volume Group name and busy SWRaid members are
accessed via the array device, /dev entry.  Therefore choose to show the
array device in the mount point field for busy SWRaid members.

The kernel device name for an SWRaid array (without leading "/dev/") is
the same as used in /proc/mdstat and /proc/partitions.  Therefore the
array device (with leading "/dev/") displayed in GParted will match
between the mount point for busy SWRaid members and the array itself as
used in the device combo box.

    # cat /proc/mdstat
    Personalities : [raid1]
    md1 : active raid1 sda1[2] sdb1[3]
          524224 blocks super 1.0 [2/2] [UU]
    ...
    # cat /proc/partitions
    major minor  #blocks  name

       8        0   33554432 sda
       8        1     524288 sda1
    ...
       8       16   33554432 sdb
       8       17     524288 sdb1
    ...
       9        1     524224 md1
    ...

Bug 756829 - SWRaid member detection enhancements
2015-11-02 10:03:45 -07:00
Mike Fleetwood 7255c8af40 Use UUID and label of SWRaid arrays too (#756829)
In cases where blkid wrongly reports a file system instead of an SWRaid
member (sometimes confused by metadata 0.90/1.0 mirror array or old
version not recognising SWRaid members), the UUID and label are
obviously wrong too.  Therefore have to use the UUID and label returned
by the mdadm query command and never anything reported by blkid or any
file system specific command.

Example of blkid reporting the wrong type, UUID and label for /dev/sda1
and the correct values for /dev/sdb1:

    # blkid | egrep 'sd[ab]1'
    /dev/sda1: UUID="10ab5f7d-7d8a-4171-8b6a-5e973b402501" TYPE="ext4" LABEL="chimney-boot"
    /dev/sdb1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="0a095e45-9360-1b17-0ad1-1fe369e22b98" LABEL="chimney:1" TYPE="linux_raid_member"

    # mdadm -E -s -v
    ARRAY /dev/md/1  level=raid1 metadata=1.0 num-devices=2 UUID=15224a42:c25bbcd9:15db6000:4e5fe53a name=chimney:1
       devices=/dev/sda1,/dev/sdb1
    ...
    ARRAY /dev/md127 level=raid1 num-devices=2 UUID=8dc7483c:d74ee0a8:b6a8dc3c:a57e43f8
       devices=/dev/sdb6,/dev/sda6
    ...

NOTES:
* In mdadm terminology the label is called the array name, hence name=
  parameter for array md/1 in the above output.
* Metadata 0.90 arrays don't support naming, hence the missing name=
  parameter for array md127 in the above output.

Bug 756829 - SWRaid member detection enhancements
2015-11-02 10:03:45 -07:00
Mike Fleetwood 0ce9857380 Move busy detection of SWRaid members into the new module (#756829)
Add active attribute to the cache of SWRaid members.  Move parsing of
/proc/mdstat to discover busy SWRaid members into the cache loading
code.  New parsing code is a little different because it is finding all
members of active arrays rather than determining if a specific member is
active.

Bug 756829 - SWRaid member detection enhancements
2015-11-02 10:03:45 -07:00
Mike Fleetwood 5f02bcf463 Detect Linux SWRaid members by querying mdadm (#756829)
Detection of Linux SWRaid members currently fails in a number of cases:

1)  Arrays which use metadata type 0.90 or 1.0 store the super block at
    the end of the partition.  So file system signatures in at least
    linear and mirrored arrays occur at the same offsets in the
    underlying partitions.  As libparted only recognises file systems
    this is what is detected, rather than an SWRaid member.

    # mdadm -E -s -v
    ARRAY /dev/md/1  level=raid1 metadata=1.0 num-devices=2 UUID=15224a42:c25bbcd9:15db6000:4e5fe53a name=chimney:1
       devices=/dev/sda1,/dev/sdb1
    ...
    # wipefs /dev/sda1
    offset               type
    ----------------------------------------------------------------
    0x438                ext4   [filesystem]
                         LABEL: chimney-boot
                         UUID:  10ab5f7d-7d8a-4171-8b6a-5e973b402501

    0x1fffe000           linux_raid_member   [raid]
                         LABEL: chimney:1
                         UUID:  15224a42-c25b-bcd9-15db-60004e5fe53a

    # parted /dev/sda print
    Model: ATA VBOX HARDDISK (scsi)
    Disk /dev/sda: 34.4GB
    Sector size (logical/physical): 512B/512B
    Partition Table: msdos

    Number  Start   End     Size    Type      File system  Flags
     1      1049kB  538MB   537MB   primary   ext4         boot, raid
    ...

2)  Again with metadata type 0.90 or 1.0 arrays blkid may report the
    contained file system instead of an SWRaid member.  Have a single
    example of this configuration with a mirrored array containing the
    /boot file system.  Blkid reports one member as ext4 and the other as
    SWRaid!

    # blkid | egrep 'sd[ab]1'
    /dev/sda1: UUID="10ab5f7d-7d8a-4171-8b6a-5e973b402501" TYPE="ext4" LABEL="chimney-boot"
    /dev/sdb1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="0a095e45-9360-1b17-0ad1-1fe369e22b98" LABEL="chimney:1" TYPE="linux_raid_member"

    Bypassing the blkid cache gets the correct result.

    # blkid -c /dev/null /dev/sda1
    /dev/sda1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="d0460f90-d11a-e80a-ee1c-3d104dae7e5d" LABEL="chimney:1" TYPE="linux_raid_member"

    However this can't be used because if a user has a floppy configured
    in the BIOS but no floppy attached, GParted will wait for minutes as
    the kernel tries to access non-existent hardware on behalf of the
    blkid query.  See commit:
        18f863151c
        Fix long scan problem when BIOS floppy setting incorrect

3)  Old versions of blkid don't recognise SWRaid members at all so always
    report the file system when found.  Occurs with blkid v1.0 on
    RedHat / CentOS 5.

The only way I can see how to fix all these cases is to use the mdadm
command to query the configured arrays.  Then use this information for
first choice when detecting partition content, making the order: SWRaid
members, libparted, blkid and internal.

GParted shell wrapper already creates temporary blank udev rules to
prevent Linux Software RAID arrays being automatically started when
GParted refreshes its device information[1].  However an administrator
could manually stop or start arrays or change their configuration
between refreshes so GParted must load this information every refresh.
On my desktop with 4 internal hard drives and 3 testing Linux Software
RAID arrays, running mdadm adds between 0.20 and 0.30 seconds to the
device refresh time.

[1] a255abf343
    Prevent GParted starting stopped Linux Software RAID arrays (#709640)

Bug 756829 - SWRaid member detection enhancements
2015-11-02 10:03:45 -07:00
Mike Fleetwood 037020b116 Create new method GParted_Core::useable_device() (#755495)
Abstract code checking sector size and ensuring the first sector of a
candidate disk device can be read into new
GParted_Core::useable_device() method.

Bug 755495 - GParted allowing partitioning of large sector devices
             specified on the command line, when built with old
             libparted which doesn't support it
2015-10-08 13:00:01 -06:00
Mike Fleetwood d925bd2bb5 Stop including removed <sigc++/class_slot.h> header (#756035)
Libsigc++2 version 2.5.2 and later removed header file
<sigc++/class_slot.h>.  Quoting the NEWS file for version 2.5.2:

    Remove useless headers: sigc++/class_slot.h ...

Libsigc++2 version 2.5.2 NEWS file:
https://git.gnome.org/browse/libsigc++2/tree/NEWS?id=2.5.2

Bug 756035 - GParted does not compile with newer gtkmm libraries in
             Fedora 23
2015-10-05 10:14:35 -06:00
Albert Young 584137b32b Remove prohibited characters from FAT16/32 labels (#755608)
GParted waits forever when attempting to set a FAT16/32 file system
label which contains prohibited characters [1][2].  This is because
mlabel asks a question and is waiting for input.  Force cancelling the
operation doesn't work either as GParted sends signal 2 (interrupt i.e.
[Ctrl-C]) but mtools commands specifically ignores this and a number of
other signals.  Have to kill mlabel with signal 9 (kill) to regain
control of GParted.

Mlabel command with prohibited characters in the label:

    # export MTOOLS_SKIP_CHECK=1
    # mlabel ::"MYLABEL/   " -i /dev/sdb10
    Long file name "MYLABEL/   " contains illegal character(s).
    a)utorename A)utorename-all r)ename R)ename-all
    s)kip S)kip-all q)uit (aArRsSq):

Remove prohibited characters from FAT16/32 file systems labels when
creating and labelling them.  Also upper case the label to meet label
requirements [1][2].  This silently corrects the label and the actual
label applied will be displayed when GParted refreshes after applying
the operation.

[1] Microsoft TechNet: Label
    https://technet.microsoft.com/en-us/library/bb490925.aspx

[2] Replicated in Wikikedia: label (command)
    https://en.wikipedia.org/wiki/Label_%28command%29

Bug 755608 - Labeling fat16/fat32 partitions hangs if certain characters
             included in label
2015-10-04 09:57:07 -06:00
Mike Fleetwood cbfb7e51f5 Replace Operation class members index and index_extended with local variables (#755214)
These member variables store no Operation class information and were
being used as local variables.  Replace with local variables.

Also indent a code block within an if clause so that the compiler can
confirm that the new local variable isn't used uninitialised.  Prevents
this compiler warning:
    OperationResizeMove.cc: In member function 'void GParted::OperationResizeMove::apply_normal_to_visual(std::vector<GParted::Partition, std::allocator<GParted::Partition> >&)':
    OperationResizeMove.cc:125: warning: 'index' may be used uninitialized in this function

Bug 755214 - Refactor operation merging
2015-09-28 11:02:07 -06:00
Mike Fleetwood a1ab21285b Remove unused index parameter from Add_Operation() (#755214)
Since this commit earlier in the patchset the second optional parameter
of method Win_GParted::Add_Operation() is no longer used.  Remove it.
    Replace open coded merge of resize/move into create operation
    (#755214)

Bug 755214 - Refactor operation merging
2015-09-28 11:02:07 -06:00
Mike Fleetwood dc6ffc6a87 Move code visually re-applying create operation into parent class (#755214)
Move the code from OperationCreate::apply_to_visual() into new method
Operation::insert_new() in the parent class.  This is in preparation for
the following commit.

Bug 755214 - Refactor operation merging
2015-09-28 10:41:39 -06:00
Mike Fleetwood 27cbe36d0f Share duplicate code substituting partitions in multiple operations (#755214)
The apply_to_visual() method for the change UUID, format, label file
system and name partition operations duplicated identical code.  This
code was just substituting the partition in the disk graphic vector with
the new partition recorded in the operation, as none of these operations
change the partition boundaries.  Move this duplicate code into the
parent class in new method Operation::substitute_new().

Bug 755214 - Refactor operation merging
2015-09-28 10:41:39 -06:00
Mike Fleetwood 9b497aae14 Fix visually re-applying create operation in create-create-grow-first sequence (#755214)
After previous commit "Replace open coded merge of resize/move into
create operation (#755214)" the second created partition would disappear
from the disk graphic in the following sequence: create new #1, create
new #2 leaving space preceding, resize #1 larger.  The create new #2
operation still existed and was shown in the operation list.  It was
just that it disappeared from the disk graphic.

Remember that when each operation is created it records the partition,
or the unallocated space, to which the operation is applied at the time
the operation is created in the partition_original member variable.  In
the above sequence the resize #1 larger operation was merged back into
the create new #1 operation.  When visually re-applying the create
new #1 operation to the disk graphic, it left a smaller unallocated
partition following it.  This was smaller than the unallocated partition
recorded in the create new #2 operation, hence it failed to visually
re-apply to the disk graphic.

The insight to fix this is that it doesn't matter what size the
unallocated space was when the create new operation was constructed.  It
only matters that the new partition to be created fits in the available
unallocated space currently in the disk graphic.

Bug 755214 - Refactor operation merging
2015-09-28 10:41:39 -06:00
Mike Fleetwood cf5d8d928c Refactor merging rules into new merge_operations() (#755214)
Creation of the various operations involved various implicit rules about
how the different types of operations were merged in different cases.
This was open coded in each ::activate_*() method.  Abstract this into
new merge_operations() method and make the merging rules explicitly
specified.

NOTE:
The removal of operation type checking in the MERGE_LAST_WITH_ANY cases
is not a problem because all the Operation*::merge_operations() methods
ensure the operation types match as part of the merge attempt.

Bug 755214 - Refactor operation merging
2015-09-28 10:41:39 -06:00
Mike Fleetwood d93d8abcc4 Rename function to merge_two_operations() and update validation (#755214)
Rename Win_GParted::Merge_Operations() to merge_two_operations().  To
reflect what it does and in preparation for further refactoring of the
code.

Be more strict on the validation of the first and second indexes.  The
first operation must also be before the second operation in the
operation[] vector.  (It is actually a programming bug if first and
second fail validation.  However so far g_assert() is only being used to
validate pointers, which if wrong would likely cause the program to
eventually crash when dereferenced later.  In this case a bug would
merely cause the incorrectly specified pair of operations to not be
merged).

Move validate_display_partition_ptr() declaration in the header file to
be in the same ordering as it's definition in the source file.

Bug 755214 - Refactor operation merging
2015-09-28 10:41:39 -06:00
Mike Fleetwood 7f4ffd28d5 Encapsulate operation merging inside the Operation* classes (#755214)
Win_GParted::Merge_Operations() method was modifying the internals of
Operation* objects; in particular the partition_new member variable.
This is breaking data hiding and encapsulation tenant of object oriented
programming.

Implement exactly the same operation merge semantics, but hide the
manipulation of the internals of the Operation* objects within the
Operation* classes themselves.

Bug 755214 - Refactor operation merging
2015-09-28 10:41:39 -06:00
Mike Fleetwood 26dc3dffa7 Localise checking for an extended partition into activate_new()
As previous commit, display_partitions is now a Win_GParted member
variable so checking for the existence of an extended partition can be
localised where it is used.

Remove index_extended member variable and localise the same checking in
activate_new().
2015-09-22 09:50:11 -06:00
Mike Fleetwood 3b5471516c Localise counting of primary partitions into max_amount_prim_reached()
Now that display_partitions is a Win_GParted member variable and
therefore available throughout the class, since commit [1], calculation
of primary_count can be localised in max_amount_prim_reached() where it
is used.

Implements a FIXME and removes primary_count as a member variable.

[1] 545b75d957
    Move vector of partition objects to a Win_GParted class member (#750168)
2015-09-22 09:50:11 -06:00
Mike Fleetwood 0e32d39189 Remove unused public member variable FileSystem::success
Assume accidentally added in commit:
    52a2a9b00a
    Reduce threading (#685740)
2015-09-21 10:11:19 -06:00
Mike Fleetwood 2b57229fc2 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-21 10:11:19 -06:00
Mike Fleetwood 3eccd01f42 Time and check nearly all file system action commands (#754684)
There has been an undocumented rule that external commands displayed in
the operation details, as part of file system manipulations, only get a
time and check mark displayed when multiple commands are needed, and not
otherwise.  (GParted checks whether all commands are successful or not
regardless of whether a check mark is displayed in the operation details
or not).

EXCEPTION 1: btrfs resize

Since the following commit [1] from 2013-02-22, GParted stopped
displaying the timing for the btrfs resize command in the operation
details.  It being part of a multi-command sequence to perform the step.
This is because FileSystem::execute_command() since the commit can only
check the exit status for zero / non-zero while timing and checking the
command status but btrfs resize needs to consider some non-zero statuses
as successful.

[1] 52a2a9b00a
    Reduce threading (#685740)

EXCEPTION 2: ext2/3/4 move and copy using e2image

When use of e2image was added [2] the single command steps were timed
and check.

[2] 86111fe12a
    Use e2image to move/copy ext[234] file systems (#721516)

EXCEPTION 3: fat16/32 write label and UUID

Uses Utils::execute_command() rather than FileSystem::execute_command()
so can be separately changed.  See the following commit for resolution
of the final commands not yet timed and check mark displayed.

CHANGE:

Lets make a simpler rule of always displaying the time and a check mark
for all external commands displayed in the operation details.  However
this makes several of the other single command actions need special exit
status handling because zero success, non-zero failure is not correct
for every case.  Specifically affects resizing of reiserfs and check
repair of ext2/3/4, fat16/32, jfs and reiserfs.

After this change all external commands run as file system actions must
follow one of these two patterns of using the EXEC_CHECK_STATUS flag or
separately calling FileSystem::set_status() to register success or
failure of the command:
    exit_status = execute_command(cmd, od, EXEC_CHECK_STATUS...);
or:
    exit_status = execute_command(cmd, od, ...);
    bool success = (exit_status == 0 || exit_status == OTHER_SUCCESS_VALUE...);
    set_status(od, success );

Bug 754684 - Updates to FileSystem:: and Utils::execute_command()
             functions
2015-09-21 10:11:19 -06:00
Mike Fleetwood 83ecae4918 Refactor flags in method FileSystem::execute_command() (#754684)
Change the two optional boolean parameters into a single optional flags
parameter which uses symbolically defined names.  Makes reading the
execute_command() calls much easier to understand.  (Implemented as bit
field using the same technique as used for Glib::SpawnFlags [1]).

This changes the calls thus:

  execute_command(cmd, od)              -> (cmd, od)
  execute_command(cmd, od, false)       -> (cmd, od, EXEC_NONE)  // [2]
  execute_command(cmd, od, true )       -> (cmd, od, EXEC_CHECK_STATUS)
  execute_command(cmd, od, false, true) -> (cmd, od, EXEC_CANCEL_SAFE)
  execute_command(cmd, od, true , true) ->
                          (cmd, od, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE)

[1] SpawnFlags bitwise operators in
    /usr/include/glibmm-2.4/glibmm/spawn.h.

[2] False and EXEC_NONE are the default values for the optional third
    parameter before and after this change respectively and both mean
    the same.  This is being used in btrfs::resize() and being kept for
    now despite it being the default.

Bug 754684 - Updates to FileSystem:: and Utils::execute_command()
             functions
2015-09-21 10:11:19 -06:00