gparted/src/Dialog_Partition_Info.cc

660 lines
26 KiB
C++
Raw Permalink Normal View History

/* Copyright (C) 2004 Bart
* Copyright (C) 2008, 2009, 2010 Curtis Gedak
2004-09-19 14:24:53 -06:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
2004-09-19 14:24:53 -06:00
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
2004-09-19 14:24:53 -06:00
*/
#include "Dialog_Partition_Info.h"
#include "LVM2_PV_Info.h"
#include "Partition.h"
#include "PartitionLUKS.h"
#include "Utils.h"
#include "btrfs.h"
2004-09-19 14:24:53 -06:00
#include <glibmm/miscutils.h>
#include <gtkmm/alignment.h>
#include <gtkmm/viewport.h>
#include <gtkmm/grid.h>
#include <gtkmm/label.h>
#include <atkmm/relation.h>
#include <gdkmm/general.h>
2004-09-19 14:24:53 -06:00
namespace GParted
{
Dialog_Partition_Info::Dialog_Partition_Info( const Partition & partition ) : partition( partition )
2004-09-19 14:24:53 -06:00
{
// Set minimum dialog height so it fits on an 800x600 screen without too much
// whitespace (~500 px max for GNOME desktop). Allow extra space if have any
// messages or for LVM2 PV or LUKS encryption.
if (partition.have_messages() ||
partition.fstype == FS_LVM2_PV ||
partition.fstype == FS_LUKS )
this ->set_size_request( -1, 460) ;
else
this ->set_size_request( -1, 370 ) ; //Minimum 370 to avoid scrolling on Fedora 20
2004-09-19 14:24:53 -06:00
/*TO TRANSLATORS: dialogtitle, looks like Information about /dev/hda3 */
this ->set_title( Glib::ustring::compose( _("Information about %1"), partition .get_path() ) );
init_drawingarea() ;
// Place info and optional messages in scrollable window
info_msg_vbox.set_orientation(Gtk::ORIENTATION_VERTICAL);
info_msg_vbox .set_border_width( 6 ) ;
info_scrolled .set_policy( Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC ) ;
Request natural width in Gtk::ScrolledWindows for Gtk >= 3.22 (!39) Before Gtk 3.22 GtkScrolledWindow propagated natural size to its Children and so on to descendants. In Gtk 3.22 this was changed to always request the minimum size. This was done because it is believed to be a safer default (gives a better behaviour) in case of dynamic content inside the scrolled window, that is, content that may change allocated size. [1][2][3] When the scrolled window content is not dynamic the natural size is preferable because it gives a better looking layout and without any downside. In the case of GParted content which is not dynamic, so request the scrolled windows to allocate children at natural sizes for Gtk >= 3.22. The benefits of natural size allocation are evident in presence of wrapping labels (for example inside the "Partition Info" dialog), that with the minimum size request likely end up taking a very small width. References: [1] Gtk commit from 2016-08-31: GtkScrolledWindow: Make propagation of natural child sizes optional https://gitlab.gnome.org/GNOME/gtk/commit/0984d1622d022bf67207f985f7842b6299818e20 "Making propagation of child natural sizes mandatory (or default, even) was evidently a mistake as this causes dynamic content in a scrolled window to resize it's parent when the scrolled window is competing for space with an adjacent widget." [2] Gtk 3.22 Reference Documentation - gtk_scrolled_window_set_propagate_natural_width https://developer.gnome.org/gtk3/3.22/GtkScrolledWindow.html#gtk-scrolled-window-set-propagate-natural-width [3] Gtkmm 3.24 Gtk::ScrolledWindow Class Reference, set_propagate_natural_width() method https://developer.gnome.org/gtkmm/3.24/classGtk_1_1ScrolledWindow.html#a2d4cb945688ecb8739efd70b18742779 [4] Gtkmm 3.21.6 NEWS https://gitlab.gnome.org/GNOME/gtkmm/blob/3.21.6/NEWS "ScrolledWindow: Added get/set_propagate_natural_height/width() and the properties." Closes !39 - Always request natural size inside Gtk::ScrolledWindow
2019-05-01 04:57:38 -06:00
#if HAVE_SET_PROPAGATE_NATURAL_WIDTH
info_scrolled.set_propagate_natural_width(true);
#endif
info_scrolled .add( info_msg_vbox ) ;
// As Gtk::Box widget info_msg_vbox doesn't have a native scrolling capability a
// Gtk::Viewport is automatically created to contain it when it is added to the
// Gtk::ScrolledWindow widget info_scrolled. The Viewport widget is created with
// shadow type GTK_SHADOW_IN by default. Change to GTK_SHADOW_NONE.
Gtk::Viewport * child_viewport = dynamic_cast<Gtk::Viewport *>(info_scrolled.get_child());
if (child_viewport)
child_viewport->set_shadow_type(Gtk::SHADOW_NONE);
//horizontally center the information scrolled window to match partition graphic
Gtk::Alignment * center_widget = manage( new Gtk::Alignment(0.5, 0.5, 0.0, 1.0) ) ;
center_widget ->add( info_scrolled ) ;
this->get_content_area()->pack_start(*center_widget);
2004-09-19 14:24:53 -06:00
//add label for detail and fill with relevant info
Display_Info() ;
2004-09-19 14:24:53 -06:00
//display messages (if any)
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
if ( partition.have_messages() )
2004-09-19 14:24:53 -06:00
{
frame = manage( new Gtk::Frame() );
{
Gtk::Image* image = Utils::mk_image(Gtk::Stock::DIALOG_WARNING, Gtk::ICON_SIZE_BUTTON);
hbox = manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
hbox->pack_start(*image, Gtk::PACK_SHRINK);
}
hbox ->pack_start( * Utils::mk_label( "<b> " + Glib::ustring(_("Warning:") ) + " </b>" ),
Gtk::PACK_SHRINK ) ;
2004-09-19 14:24:53 -06:00
frame ->set_label_widget( *hbox ) ;
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
// Concatenate all messages for display so that they can be selected
// together. Use a blank line between individual messages so that each
// message can be distinguished. Therefore each message should have been
// formatted as one or more non-blank lines, with an optional trailing new
// line. This is true of GParted internal messages and probably all
// external messages and errors from libparted and executed commands too.
std::vector<Glib::ustring> messages = partition.get_messages();
Glib::ustring concatenated_messages;
for ( unsigned int i = 0; i < messages.size(); i ++ )
{
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
if ( concatenated_messages.size() > 0 )
concatenated_messages += "\n\n";
concatenated_messages += "<i>" + Utils::trim_trailing_new_line(messages[i]) + "</i>";
}
Gtk::Box *vbox = manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
vbox ->set_border_width( 5 ) ;
Display messages for encrypted file systems (#760080) At the moment any messages for an encrypted file system aren't shown, only messages from the outer PartitionLUKS object are shown. Also in Win_GParted::activate_paste() the selected Partition object, possibly a derived PartitionLUKS, is cloned and the messages cleared. Therefore a set of accessor methods must be provided to query and modify partition messages. Messages will be stored in the Partition object to which they are added and retrieved from all. So in the case of a derived PartitionLUKS they will be retrieved from the messages vector of the PartitionLUKS object itself and the messages vector for the encrypted file system it contains. To replace code like this in GParted_Core: partition_temp->messages = messages; We might naturally provide a set_messages() method which assigns the messages vector and is used like this: partition_temp->set_messages( messages ); However on a PartitionLUKS object what should set_messages() do? By the name it will replace any existing messages in the PartitionLUKS object itself, but what should happen to the messages for the contained encrypted Partition object? Should they be cleared or left alone? Rather than implement set_messages() with unclear semantics implement append_messages(), which in the PartitionLUKS object case will clearly leave any messages for the contained encrypted Partition object alone. Append_messages() is then used to add messages as the Partition or PartitionLUKS objects when populating the data in GParted_Core. Bug 760080 - Implement read-only LUKS support
2015-12-31 09:32:08 -07:00
vbox->pack_start( *Utils::mk_label( concatenated_messages, true, true, true ), Gtk::PACK_SHRINK );
frame ->add( *vbox ) ;
info_msg_vbox .pack_start( *frame, Gtk::PACK_EXPAND_WIDGET ) ;
2004-09-19 14:24:53 -06:00
}
this ->add_button( Gtk::Stock::CLOSE, Gtk::RESPONSE_OK ) ;
this ->show_all_children() ;
2004-09-19 14:24:53 -06:00
}
bool Dialog_Partition_Info::drawingarea_on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
2004-09-19 14:24:53 -06:00
{
Gdk::Cairo::set_source_rgba(cr, color_partition);
cr->rectangle(0, 0, 400, 60);
cr->fill();
if (partition.fstype != FS_UNALLOCATED)
2004-09-19 14:24:53 -06:00
{
// Used
Gdk::Cairo::set_source_rgba(cr, color_used);
cr->rectangle(BORDER,
BORDER,
used,
60 - 2 * BORDER);
cr->fill();
// Unused
Gdk::Cairo::set_source_rgba(cr, color_unused);
cr->rectangle(BORDER + used,
BORDER,
unused,
60 - 2 * BORDER);
cr->fill();
// Unallocated
Gdk::Cairo::set_source_rgba(cr, color_unallocated);
cr->rectangle(BORDER + used + unused,
BORDER,
unallocated,
60 - 2 * BORDER);
cr->fill();
2004-09-19 14:24:53 -06:00
}
// Text
Gdk::Cairo::set_source_rgba(cr, color_text);
cr->move_to(180, BORDER + 6);
pango_layout->show_in_cairo_context(cr);
2004-09-19 14:24:53 -06:00
return true;
}
void Dialog_Partition_Info::init_drawingarea()
2004-09-19 14:24:53 -06:00
{
drawingarea .set_size_request( 400, 60 ) ;
drawingarea.signal_draw().connect(sigc::mem_fun(*this, &Dialog_Partition_Info::drawingarea_on_draw));
frame = manage( new Gtk::Frame() ) ;
frame ->add( drawingarea ) ;
2004-09-19 14:24:53 -06:00
frame ->set_shadow_type( Gtk::SHADOW_ETCHED_OUT ) ;
frame ->set_border_width( 10 ) ;
hbox = manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
2004-09-19 14:24:53 -06:00
hbox ->pack_start( *frame, Gtk::PACK_EXPAND_PADDING ) ;
this->get_content_area()->pack_start(*hbox, Gtk::PACK_SHRINK);
//calculate proportional width of used, unused and unallocated
if (partition.type == TYPE_EXTENDED)
{
//Specifically show extended partitions as unallocated
used = 0 ;
unused = 0 ;
unallocated = 400 - BORDER *2 ;
}
else if ( partition .sector_usage_known() )
{
partition .get_usage_triple( 400 - BORDER *2, used, unused, unallocated ) ;
}
else
{
//Specifically show unknown figures as unused
used = 0 ;
unused = 400 - BORDER *2 ;
unallocated = 0 ;
}
2004-09-19 14:24:53 -06:00
// Colors
color_used.set("#F8F8BA");
color_unused.set("white");
color_unallocated.set("darkgrey");
color_text.set("black");
color_partition.set(Utils::get_color(partition.get_filesystem_partition().fstype));
2004-09-19 14:24:53 -06:00
//set text of pangolayout
pango_layout = drawingarea .create_pango_layout(
partition .get_path() + "\n" + Utils::format_size( partition .get_sector_length(), partition .sector_size ) ) ;
2004-09-19 14:24:53 -06:00
}
void Dialog_Partition_Info::Display_Info()
{
//The information in this area is in table format.
//
//For example:
//<-------------------------- Column Numbers ----------------------------->
//0 1 2 3 4 5 6
//+-+------------+-------------+-------------+------------+---------------+
//Section
// Field Left: Value Left Field Right: Value Right Optional Right
//+-+------------+-------------+-------------+------------+---------------+
//0 1 2 3 4 5 6
// Refers to the Partition object containing the file system. Either the same as
// partition, or for an open LUKS mapping, the encrypted Partition object member
// within containing the encrypted file system.
const Partition & filesystem_ptn = partition.get_filesystem_partition();
Sector ptn_sectors = partition .get_sector_length() ;
Glib::ustring vgname = "" ; //Also used in partition status message
if (filesystem_ptn.fstype == FS_LVM2_PV)
vgname = LVM2_PV_Info::get_vg_name( filesystem_ptn.get_path() );
bool filesystem_accessible = false;
if (partition.fstype != FS_LUKS || partition.busy)
// As long as this is not a LUKS encrypted partition which is closed the
// file system is accessible.
filesystem_accessible = true;
Gtk::Grid *grid(Gtk::manage(new Gtk::Grid()));
grid->set_border_width(5);
grid->set_column_spacing(10);
info_msg_vbox.pack_start(*grid, Gtk::PACK_SHRINK);
// FILE SYSTEM DETAIL SECTION
// File system headline
grid->attach(*Utils::mk_label("<b>" + Glib::ustring(_("File System")) + "</b>"), 0, 0, 6, 1);
// Initialize grid top attach tracker (left side of the grid)
int top = 1;
// Left field & value pair area
// File system
Gtk::Label *label_filesystem = Utils::mk_label("<b>" + Glib::ustring(_("File system:")) + "</b>");
grid->attach(*label_filesystem, 1, top, 1, 1);
if ( filesystem_accessible )
{
Gtk::Label *value_filesystem = Utils::mk_label(Utils::get_filesystem_string(filesystem_ptn.fstype),
true, false, true);
grid->attach(*value_filesystem, 2, top, 1, 1);
value_filesystem->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_filesystem->get_accessible());
}
top++;
//label
if (filesystem_ptn.fstype != FS_UNALLOCATED && filesystem_ptn.type != TYPE_EXTENDED)
{
Gtk::Label *label_label = Utils::mk_label("<b>" + Glib::ustring(_("Label:")) + "</b>");
grid->attach(*label_label, 1, top, 1, 1);
if ( filesystem_accessible )
{
Gtk::Label *value_label = Utils::mk_label(filesystem_ptn.get_filesystem_label(),
true, false, true);
grid->attach(*value_label, 2, top, 1, 1);
value_label->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_label->get_accessible());
}
top++;
2004-09-19 14:24:53 -06:00
}
// file system uuid
if (filesystem_ptn.fstype != FS_UNALLOCATED && filesystem_ptn.type != TYPE_EXTENDED)
{
Gtk::Label *label_uuid = Utils::mk_label("<b>" + Glib::ustring(_("UUID:")) + "</b>");
grid->attach(*label_uuid, 1, top, 1, 1);
if ( filesystem_accessible )
{
Gtk::Label *value_uuid = Utils::mk_label(filesystem_ptn.uuid, true, false, true);
grid->attach(*value_uuid, 2, top, 1, 1);
value_uuid->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_uuid->get_accessible());
}
top++;
}
/* TO TRANSLATORS: Open
* means that the LUKS encryption is open and the encrypted data within is accessible.
*/
static Glib::ustring luks_open = _("Open");
/* TO TRANSLATORS: Closed
* means that the LUKS encryption is closed and the encrypted data within is not accessible.
*/
static Glib::ustring luks_closed = _("Closed");
//status
if (filesystem_ptn.fstype != FS_UNALLOCATED && filesystem_ptn.status != STAT_NEW)
2004-09-19 14:24:53 -06:00
{
//status
Glib::ustring str_temp ;
Gtk::Label *label_status = Utils::mk_label("<b>" + Glib::ustring(_("Status:")) + "</b>",
true, false, false, Gtk::ALIGN_START);
grid->attach(*label_status, 1, top, 1, 1);
if ( ! filesystem_accessible )
{
/* TO TRANSLATORS: Not accessible (Encrypted)
* means that the data in encrypted and hasn't been made
* accessible by opening it with the passphrase.
*/
str_temp = _("Not accessible (Encrypted)");
}
else if ( filesystem_ptn.busy )
{
if ( filesystem_ptn.type == TYPE_EXTENDED )
{
/* TO TRANSLATORS: Busy (At least one logical partition is mounted)
* means that this extended partition contains at least one logical
* partition that is mounted or otherwise active.
*/
str_temp = _("Busy (At least one logical partition is mounted)") ;
}
else if (filesystem_ptn.fstype == FS_LINUX_SWAP ||
filesystem_ptn.fstype == FS_LINUX_SWRAID ||
filesystem_ptn.fstype == FS_ATARAID ||
filesystem_ptn.fstype == FS_LVM2_PV ||
Report busy status of jbds (#89) Continuing from the state in the previous commit, create an ext4 file system using the previously created external journal and mount it. # mke2fs -t ext4 -J device=/dev/sdb1 -L test-ext4 /dev/sdb2 # mount /dev/sdb2 /mnt/2 Did some experimenting with trying to create a second file system using the same external journal which is already in use. # mke2fs -t ext4 -J device=/dev/sdb1 -L 2nd-test-ext4 /dev/sdb3 ... /dev/sdb1 is apparently in use by the system; will not make a journal here! # exit $? 1 Examined the source code of mke2fs and found that it performs an exclusive read-only open of the named journal block device to check if it is in use by the system or not [1]. Use the same method in GParted. Not used alternative method would be to mark the jbd active when the ext3/4 file system using it is active, but that requires working out the linkage between them. That can be done using either blkid or dumpe2fs output but that involves parsing more fields and caching more data so is much more code than just testing the block device busy status using the same method which mke2fs uses. Matching UUIDs via blkid output. # blkid /dev/sdb1 /dev/sdb2 /dev/sdb1: LABEL="test-jbd" UUID="6e52858e-0479-432f-80a1-de42f9a4093e" TYPE="jbd" /dev/sdb2: LABEL="test-ext4" UUID="cea5c2cd-b21c-4abf-a497-8c073bb12300" EXT_JOURNAL="6e52858e-0479-432f-80a1-de42f9a4093e" TYPE="ext4" Matching UUIDs via dumpe2fs output. # dumpe2fs -h /dev/sdb1 | egrep 'Filesystem UUID|Journal users' dumpe2fs 1.46.3 (27-Jul-2021) Filesystem UUID: 6e52858e-0479-432f-80a1-de42f9a4093e Journal users: cea5c2cd-b21c-4abf-a497-8c073bb12300 # dumpe2fs -h /dev/sdb2 | egrep 'Filesystem UUID|Journal UUID' dumpe2fs 1.46.3 (27-Jul-2021) Filesystem UUID: cea5c2cd-b21c-4abf-a497-8c073bb12300 Journal UUID: 6e52858e-0479-432f-80a1-de42f9a4093e If GParted was going to show the journal to file system linkage in the UI then doing this would be needed. However so far there has only been a single reported case of a GParted user using an external journal, therefore adding the code complexity for this feature is not currently justified. The simple busy detection method used by mke2fs is all that is needed. [1] mke2fs source code https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/ misc/mke2fs.c:main() check_mount(journal_device, force, _("journal")); misc/util.c:check_mount() ext2fs_check_if_mounted(device, &mount_flags); lib/ext2fs/ismounted.c:ext2fs_check_if_mounted() ext2fs_check_mount_point(file, mount_flags, NULL, 0); lib/ext2fs/ismounted.c:ext2fs_check_if_mounted() if (stat(device, &st_buf) == 0 && ext2fsP_is_disk_device(st_buf.st_mode)) { int fd = open(device, O_RDONLY | O_EXCL); if (fd >= 0) { /* * The device is not busy so it's * definitelly not mounted. No need to * to perform any more checks. */ close(fd); *mount_flags = 0; return 0; } else if (errno == EBUSY) { busy = 1; } } Closes #89 - GParted doesn't recognise EXT4 fs journal partition
2022-01-25 15:31:55 -07:00
filesystem_ptn.fstype == FS_BCACHE ||
filesystem_ptn.fstype == FS_JBD )
{
/* TO TRANSLATORS: Active
* means that this linux swap, linux software raid partition, or
* LVM physical volume is enabled and being used by the operating system.
*/
str_temp = _("Active") ;
}
else if (filesystem_ptn.fstype == FS_LUKS)
{
// NOTE: LUKS within LUKS
// Only ever display LUKS information in the file system
// section when the contents of a LUKS encryption is
// another LUKS encryption!
str_temp = luks_open;
}
else if ( filesystem_ptn.get_mountpoints().size() )
{
str_temp = Glib::ustring::compose(
/* TO TRANSLATORS: looks like Mounted on /mnt/mymountpoint */
_("Mounted on %1"),
Glib::build_path( ", ", filesystem_ptn.get_mountpoints() ) );
}
}
else if ( filesystem_ptn.type == TYPE_EXTENDED )
{
/* TO TRANSLATORS: Not busy (There are no mounted logical partitions)
* means that this extended partition contains no mounted or otherwise
* active partitions.
*/
str_temp = _("Not busy (There are no mounted logical partitions)") ;
}
else if (filesystem_ptn.fstype == FS_LINUX_SWAP ||
filesystem_ptn.fstype == FS_LINUX_SWRAID ||
filesystem_ptn.fstype == FS_ATARAID ||
Report busy status of jbds (#89) Continuing from the state in the previous commit, create an ext4 file system using the previously created external journal and mount it. # mke2fs -t ext4 -J device=/dev/sdb1 -L test-ext4 /dev/sdb2 # mount /dev/sdb2 /mnt/2 Did some experimenting with trying to create a second file system using the same external journal which is already in use. # mke2fs -t ext4 -J device=/dev/sdb1 -L 2nd-test-ext4 /dev/sdb3 ... /dev/sdb1 is apparently in use by the system; will not make a journal here! # exit $? 1 Examined the source code of mke2fs and found that it performs an exclusive read-only open of the named journal block device to check if it is in use by the system or not [1]. Use the same method in GParted. Not used alternative method would be to mark the jbd active when the ext3/4 file system using it is active, but that requires working out the linkage between them. That can be done using either blkid or dumpe2fs output but that involves parsing more fields and caching more data so is much more code than just testing the block device busy status using the same method which mke2fs uses. Matching UUIDs via blkid output. # blkid /dev/sdb1 /dev/sdb2 /dev/sdb1: LABEL="test-jbd" UUID="6e52858e-0479-432f-80a1-de42f9a4093e" TYPE="jbd" /dev/sdb2: LABEL="test-ext4" UUID="cea5c2cd-b21c-4abf-a497-8c073bb12300" EXT_JOURNAL="6e52858e-0479-432f-80a1-de42f9a4093e" TYPE="ext4" Matching UUIDs via dumpe2fs output. # dumpe2fs -h /dev/sdb1 | egrep 'Filesystem UUID|Journal users' dumpe2fs 1.46.3 (27-Jul-2021) Filesystem UUID: 6e52858e-0479-432f-80a1-de42f9a4093e Journal users: cea5c2cd-b21c-4abf-a497-8c073bb12300 # dumpe2fs -h /dev/sdb2 | egrep 'Filesystem UUID|Journal UUID' dumpe2fs 1.46.3 (27-Jul-2021) Filesystem UUID: cea5c2cd-b21c-4abf-a497-8c073bb12300 Journal UUID: 6e52858e-0479-432f-80a1-de42f9a4093e If GParted was going to show the journal to file system linkage in the UI then doing this would be needed. However so far there has only been a single reported case of a GParted user using an external journal, therefore adding the code complexity for this feature is not currently justified. The simple busy detection method used by mke2fs is all that is needed. [1] mke2fs source code https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/ misc/mke2fs.c:main() check_mount(journal_device, force, _("journal")); misc/util.c:check_mount() ext2fs_check_if_mounted(device, &mount_flags); lib/ext2fs/ismounted.c:ext2fs_check_if_mounted() ext2fs_check_mount_point(file, mount_flags, NULL, 0); lib/ext2fs/ismounted.c:ext2fs_check_if_mounted() if (stat(device, &st_buf) == 0 && ext2fsP_is_disk_device(st_buf.st_mode)) { int fd = open(device, O_RDONLY | O_EXCL); if (fd >= 0) { /* * The device is not busy so it's * definitelly not mounted. No need to * to perform any more checks. */ close(fd); *mount_flags = 0; return 0; } else if (errno == EBUSY) { busy = 1; } } Closes #89 - GParted doesn't recognise EXT4 fs journal partition
2022-01-25 15:31:55 -07:00
filesystem_ptn.fstype == FS_BCACHE ||
filesystem_ptn.fstype == FS_JBD )
{
/* TO TRANSLATORS: Not active
* means that this linux swap or linux software raid partition
* is not enabled and is not in use by the operating system.
*/
str_temp = _("Not active") ;
}
else if (filesystem_ptn.fstype == FS_LUKS)
{
// NOTE: LUKS within LUKS
str_temp = luks_closed;
}
else if (filesystem_ptn.fstype == FS_LVM2_PV)
{
if ( vgname .empty() )
/* TO TRANSLATORS: Not active (Not a member of any volume group)
* means that the partition is not yet a member of an LVM volume
* group and therefore is not active and can not yet be used by
* the operating system.
*/
str_temp = _("Not active (Not a member of any volume group)") ;
else if ( LVM2_PV_Info::is_vg_exported( vgname ) )
/* TO TRANSLATORS: Not active and exported
* means that the partition is a member of an LVM volume group but
* the volume group is not active and not being used by the operating system.
* The volume group has also been exported making the LVM physical volumes
* ready for moving to a different computer system.
*/
str_temp = _("Not active and exported") ;
else
/* TO TRANSLATORS: Not active
* means that the partition is a member of an LVM volume group but
* the volume group is not active and not being used by the operating system.
*/
str_temp = _("Not active") ;
}
else
{
/* TO TRANSLATORS: Not mounted
* means that this partition is not mounted.
*/
str_temp = _("Not mounted") ;
}
Gtk::Label *value_status = Utils::mk_label(str_temp, true, true, true);
grid->attach(*value_status, 2, top++, 1, 1);
value_status->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_status->get_accessible());
}
//Optional, LVM2 Volume Group name
if (filesystem_ptn.fstype == FS_LVM2_PV)
{
// Volume Group
Gtk::Label *label_volume_group = Utils::mk_label("<b>" + Glib::ustring(_("Volume Group:")) + "</b>");
grid->attach(*label_volume_group, 1, top, 1, 1);
Gtk::Label *value_volume_group = Utils::mk_label(vgname, true, false, true);
grid->attach(*value_volume_group, 2, top++, 1, 1);
value_volume_group->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_volume_group->get_accessible());
}
//Optional, members of multi-device file systems
if (filesystem_ptn.fstype == FS_LVM2_PV ||
filesystem_ptn.fstype == FS_BTRFS )
{
// Members
Gtk::Label *label_members = Utils::mk_label("<b>" + Glib::ustring(_("Members:")) + "</b>",
true, false, false, Gtk::ALIGN_START);
grid->attach(*label_members, 1, top, 1, 1);
std::vector<Glib::ustring> members ;
switch (filesystem_ptn.fstype)
{
case FS_BTRFS:
members = btrfs::get_members( filesystem_ptn.get_path() );
break ;
case FS_LVM2_PV:
if ( ! vgname .empty() )
members = LVM2_PV_Info::get_vg_members( vgname );
break ;
default:
break ;
}
Gtk::Label *value_members = Utils::mk_label(Glib::build_path("\n", members), true, false, true);
grid->attach(*value_members, 2, top++, 1, 1);
value_members->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_members->get_accessible());
}
if (filesystem_ptn.fstype == FS_LVM2_PV)
{
// Logical Volumes
Gtk::Label *label_logical_volumes = Utils::mk_label("<b>" + Glib::ustring(_("Logical Volumes:")) + "</b>",
true, false, false, Gtk::ALIGN_START);
grid->attach(*label_logical_volumes, 1, top, 1, 1);
std::vector<Glib::ustring> lvs = LVM2_PV_Info::get_vg_lvs( vgname );
Gtk::Label *value_logical_volumes = Utils::mk_label(Glib::build_path("\n", lvs), true, false, true);
grid->attach(*value_logical_volumes, 2, top++, 1, 1);
value_logical_volumes->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_logical_volumes->get_accessible());
}
// Initialize grid top attach tracker (right side of the grid)
int topright = 1;
//Right field & value pair area
if ( partition .sector_usage_known() )
{
//calculate relative diskusage
int percent_used, percent_unused, percent_unallocated ;
partition .get_usage_triple( 100, percent_used, percent_unused, percent_unallocated ) ;
// Used
Gtk::Label *label_used = Utils::mk_label("<b>" + Glib::ustring(_("Used:")) + "</b>");
grid->attach(*label_used, 3, topright, 1, 1);
Gtk::Label *value_used = Utils::mk_label(Utils::format_size(partition.get_sectors_used(), partition.sector_size),
true, false, true);
grid->attach(*value_used, 4, topright, 1, 1);
grid->attach(*Utils::mk_label("( " + Utils::num_to_str(percent_used) + "% )"),
5, topright++, 1, 1);
value_used->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY, label_used->get_accessible());
// Unused
Gtk::Label *label_unused = Utils::mk_label("<b>" + Glib::ustring(_("Unused:")) + "</b>");
grid->attach(*label_unused, 3, topright, 1, 1);
Gtk::Label *value_unused = Utils::mk_label(Utils::format_size(partition.get_sectors_unused(), partition.sector_size),
true, false, true);
grid->attach(*value_unused, 4, topright, 1, 1);
grid->attach(*Utils::mk_label("( " + Utils::num_to_str(percent_unused) + "% )"),
5, topright++, 1, 1);
value_unused->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_unused->get_accessible());
//unallocated
Sector sectors_unallocated = partition .get_sectors_unallocated() ;
if ( sectors_unallocated > 0 )
{
Gtk::Label *label_unallocated = Utils::mk_label("<b>" + Glib::ustring(_("Unallocated:")) + "</b>");
grid->attach(*label_unallocated, 3, topright, 1, 1);
Gtk::Label *value_unallocated = Utils::mk_label(Utils::format_size(sectors_unallocated, partition.sector_size),
true, false, true);
grid->attach(*value_unallocated, 4, topright, 1, 1);
grid->attach(*Utils::mk_label("( " + Utils::num_to_str(percent_unallocated) + "% )"),
5, topright++, 1, 1);
value_unallocated->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_unallocated->get_accessible());
}
}
// Size
Gtk::Label *label_size = Utils::mk_label("<b>" + Glib::ustring(_("Size:")) + "</b>");
grid->attach(*label_size, 3, topright, 1, 1);
Gtk::Label *value_size = Utils::mk_label(Utils::format_size(ptn_sectors, partition.sector_size),
true, false, true);
grid->attach(*value_size, 4, topright++, 1, 1);
value_size->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY, label_size->get_accessible());
//ensure left row tracker set to largest side (left/right)
top = std::max( top, topright );
// One blank line
grid->attach(*Utils::mk_label(""), 0, top++, 6, 1);
if (partition.fstype == FS_LUKS)
{
// ENCRYPTION DETAIL SECTION
// Encryption headline
grid->attach(*Utils::mk_label("<b>" + Glib::ustring(_("Encryption")) + "</b>"),
0, top++, 6, 1);
// Encryption
Gtk::Label *label_encryption = Utils::mk_label("<b>" + Glib::ustring(_("Encryption:")) + "</b>");
grid->attach(*label_encryption, 1, top, 1, 1);
Gtk::Label *value_encryption = Utils::mk_label(Utils::get_filesystem_string(partition.fstype),
true, false, true);
grid->attach(*value_encryption, 2, top++, 1, 1);
value_encryption->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_encryption->get_accessible());
// LUKS path
Gtk::Label *label_path = Utils::mk_label("<b>" + Glib::ustring(_("Path:")) + "</b>");
grid->attach(*label_path, 1, top, 1, 1);
if ( partition.busy ) {
Gtk::Label *value_path = Utils::mk_label(partition.get_mountpoint(), true, false, true);
grid->attach(*value_path, 2, top, 1, 1);
value_path->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_path->get_accessible());
}
top++;
// LUKS uuid
Gtk::Label *label_uuid = Utils::mk_label("<b>" + Glib::ustring(_("UUID:")) + "</b>");
grid->attach(*label_uuid, 1, top, 1, 1);
Gtk::Label *value_uuid = Utils::mk_label(partition.uuid, true, false, true);
grid->attach(*value_uuid, 2, top++, 1, 1);
value_uuid->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_uuid->get_accessible());
// LUKS status
Gtk::Label *label_status = Utils::mk_label("<b>" + Glib::ustring(_("Status:")) + "</b>");
grid->attach(*label_status, 1, top, 1, 1);
Glib::ustring str_temp;
if ( partition.busy )
str_temp = luks_open;
else
str_temp = luks_closed;
Gtk::Label *value_status = Utils::mk_label(str_temp, true, false, true);
grid->attach(*value_status, 2, top++, 1, 1);
value_status->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_status->get_accessible());
// One blank line
grid->attach(*Utils::mk_label(""), 0, top++, 6, 1);
}
// PARTITION DETAIL SECTION
// Partition headline
grid->attach(*Utils::mk_label("<b>" + Glib::ustring(_("Partition")) + "</b>"),
0, top++, 6, 1);
//use current left row tracker position as anchor for right
topright = top ;
// Left field & value pair area
// Path
Gtk::Label *label_path = Utils::mk_label("<b>" + Glib::ustring(_("Path:")) + "</b>");
grid->attach(*label_path, 1, top, 1, 1);
Gtk::Label *value_path = Utils::mk_label(partition.get_path(), true, false, true);
grid->attach(*value_path, 2, top++, 1, 1);
value_path->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY, label_path->get_accessible());
if (partition.fstype != FS_UNALLOCATED && partition.status != STAT_NEW)
{
// Name
Gtk::Label *label_name = Utils::mk_label("<b>" + Glib::ustring(_("Name:")) + "</b>");
grid->attach(*label_name, 1, top, 1, 1);
Gtk::Label *value_name = Utils::mk_label(partition.name, true, false, true);
grid->attach(*value_name, 2, top++, 1, 1);
value_name->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY, label_name->get_accessible());
// Flags
Gtk::Label *label_flags = Utils::mk_label("<b>" + Glib::ustring(_("Flags:")) + "</b>");
grid->attach(*label_flags, 1, top, 1, 1);
Gtk::Label *value_flags = Utils::mk_label(Glib::build_path(", ", partition.flags), true, false, true);
grid->attach(*value_flags, 2, top++, 1, 1);
value_flags->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_flags->get_accessible());
}
// Right field & value pair area
// First sector
Gtk::Label *label_first_sector = Utils::mk_label("<b>" + Glib::ustring(_("First sector:")) + "</b>");
grid->attach(*label_first_sector, 3, topright, 1, 1);
Gtk::Label *value_first_sector = Utils::mk_label(Utils::num_to_str(partition.sector_start), true, false, true);
grid->attach(*value_first_sector, 4, topright++, 1, 1);
value_first_sector->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_first_sector->get_accessible());
// Last sector
Gtk::Label *label_last_sector = Utils::mk_label("<b>" + Glib::ustring(_("Last sector:")) + "</b>");
grid->attach(*label_last_sector, 3, topright, 1, 1);
Gtk::Label *value_last_sector = Utils::mk_label(Utils::num_to_str(partition.sector_end), true, false, true);
grid->attach(*value_last_sector, 4, topright++, 1, 1);
value_last_sector->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_last_sector->get_accessible());
// Total sectors
Gtk::Label *label_total_sectors = Utils::mk_label("<b>" + Glib::ustring(_("Total sectors:")) + "</b>");
grid->attach(*label_total_sectors, 3, topright, 1, 1);
Gtk::Label *value_total_sectors = Utils::mk_label(Utils::num_to_str(ptn_sectors), true, false, true);
grid->attach(*value_total_sectors, 4, topright++, 1, 1);
value_total_sectors->get_accessible()->add_relationship(Atk::RELATION_LABELLED_BY,
label_total_sectors->get_accessible());
2004-09-19 14:24:53 -06:00
}
Dialog_Partition_Info::~Dialog_Partition_Info()
2004-09-19 14:24:53 -06:00
{
}
} //GParted