Implement changing UUID for NTFS (#667278)

Part 4 of 4 to provide new UUID support for NTFS.

Closes Bug #667278 - Add support for setting UUID
This commit is contained in:
Rogier Goossens 2012-01-30 11:33:33 -07:00 committed by Curtis Gedak
parent 170a79b3a0
commit 4108daf15f
14 changed files with 353 additions and 19 deletions

4
README
View File

@ -129,12 +129,12 @@ Optional packages include:
btrfs-tools
e2fsprogs
dosfstools
mtools - required to read and write FAT16/32 volume labels
mtools - required to read and write FAT16/32 volume labels and UUIDs
hfsutils
hfsprogs
jfsutils
nilfs-utils
ntfsprogs
ntfsprogs / ntfs-3g
reiser4progs
reiserfsprogs
xfsprogs, xfsdump

View File

@ -1044,6 +1044,11 @@
the partition when mounting the partition.
</para>
<para>
Note that using UUIDs is not a panacea. See
<xref linkend="gparted-changing-partition-uuid"/> for
more information.
</para>
<para>
Changes in a device name might adversely affect the
following files:
<itemizedlist>
@ -1146,8 +1151,182 @@
operation in the <guilabel>Operations Pending</guilabel>
pane.
</para>
<warning>
<para>
Changing the UUID of an existing filesystem may affect the ability of a
Linux system to boot. On Windows, it may affect the validity of the
Windows Product Activation key.
</para>
<para>
Please read (one of) the following sections for more information
if this may be a concern.
</para>
</warning>
<note>
<para>
For FAT and NTFS filesystems, what GParted names, and treats as, the
UUID, is in fact its Volume Serial Number.
</para>
<para>
An NTFS filesystem also has a real UUID, but that is a different number,
which cannot and should not be changed - at all.
</para>
</note>
</listitem>
</orderedlist>
<sect4 id="gparted-linux-uuid-issues">
<title>UUIDs in Linux</title>
<para>
Modern Linux systems are usually configured to use UUIDs to locate
and identify the different filesystems or partitions when booting. Some
partition types, like LVM physical volumes, are <emphasis>only</emphasis>
identified using their UUID. Making changes to partitions may therefore
affect the Linux boot process in different ways:
</para>
<para>
<variablelist>
<varlistentry>
<term>When copying a partition</term>
<listitem>
<para>
When a copy was made of a partition, and both the original
and the copy are ever present on the same machine at the same
time, Linux may (will)
not be able to predictably identify which is which. This is caused
by the fact that the UUID is used for identification, and
both partitions, being copies, have the same UUID.
</para>
<para>
If such confusion happens at boot time, the results will be
unpredictable. One or the other will essentially be selected at random,
and possibly a different one at each boot. Over time, this random
nature of partition selection might make files seem to mysteriously
appear or disappear depending upon which partition is selected. It may
also cause severe data corruption or loss.
</para>
<para>
This can, and should, be avoided by changing the UUID of the copy. It
is safest to change the UUID of a copied partition at all times, as both
partitions, or other copies of it, may meet again on the same computer,
with unexpected and unpredictable
results.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>When changing the UUID of a partition</term>
<listitem>
<para>
When changing he UUID of a partition, Linux may no longer be able to
correctly identify the partition. If the partition is needed when
booting, this may result in a failure to boot.
</para>
<para>
Do not change a partition's UUID if that partition is not intended to be
a copy of an existing partition, unless you know what you are doing,
and prepared to deal with the consequences.
</para>
<para>
Before changing UUIDs of Windows partitions, please be sure to
read <xref linkend="gparted-windows-uuid-issues"/>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect4>
<sect4 id="gparted-windows-uuid-issues">
<title>UUIDs in Windows</title>
<para>
On NTFS and FAT filesystems, the number that GParted names, and treats as
UUID, is in fact the Volume Serial Number.
</para>
<warning>
<para>
When changing the UUID / Volume Serial Number on a partition that will
(continue to) be used on the same hardware, using the same Windows licence,
please read this section carefully.
</para>
<para>
The information in this section is provided as is.
It is believed to be accurate, but it might in fact be incorrect, or subtly
misleading. Use GParted at your own risk. If you cannot afford to take
the risk of making Windows unbootable and/or loosing your data, then do
not use GParted.
</para>
</warning>
<para>
Changing the Volume Serial Number of an NTFS or FAT partition that is used by Windows, may
have different consequences depending on the kind of partition in question.
</para>
<para>
<variablelist>
<varlistentry>
<term>UUIDs on Windows system partitions</term>
<listitem>
<para>
On Windows, the Volume Serial Number of the System partition is
usually used<footnote>
<para>
In atypical cases, the Volume Serial Number of another partition might
be the one that is used instead.
</para>
</footnote>
for Windows Product Activation (WPA). The first modification of this number will
count as a change for WPA. Subsequent modifications are 'free'.
</para>
<para>
Too many such WPA-affecting changes, like replacing the primary harddisk
or the processor, or adding memory, will invalidate the WPA key. In that
case, windows needs to be re-activated.
</para>
<para>
For NTFS filesystems only, GParted can, and will, attempt to avoid making a
change that could be WPA-affecting, by changing only half of the NTFS Volume
Serial Number. Such a half-change should also be safe, in principle.
Nevertheless, no guarantees can be given.
</para>
<para>
As there is no easy way to revert a Volume Serial Number change (it will not,
for instance, be included in a regular backup), it should not be changed
casually, and not unless one is prepared to take the risk, and re-activate
Windows when the change proved to be one too many for WPA.
</para>
<para>
As long as a partition having the <emphasis>original</emphasis> Volume Serial
Number is present at Windows boot time, WPA requirements should normally be
satisfied, and no WPA change should be noted by Windows.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry>
<term>UUIDs on data partitions</term>
<listitem>
<para>
The NTFS or FAT Volume Serial Number on a data partition is not normally used
for WPA, although there may be exceptions. Changing it should therefore not
affect WPA.
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry>
<term>UUIDs on external storage media</term>
<listitem>
<para>
On external storage media that are not permanently attached, and not present
at Windows boot time, the Volume Serial Number is not (cannot be) used for
WPA, and therefore the validity of the WPA key should not be affected when
the Volume Serial Number is changed.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect4>
</para>
</sect3>

View File

@ -48,6 +48,9 @@ const Byte_Value MEBIBYTE=(KIBIBYTE * KIBIBYTE);
const Byte_Value GIBIBYTE=(MEBIBYTE * KIBIBYTE);
const Byte_Value TEBIBYTE=(GIBIBYTE * KIBIBYTE);
const Glib::ustring UUID_RANDOM = _("(New UUID - will be randomly generated)") ;
const Glib::ustring UUID_RANDOM_NTFS_HALF = _("(Half new UUID - will be randomly generated)") ;
enum FILESYSTEM
{
FS_UNALLOCATED = 0,
@ -96,6 +99,7 @@ enum CUSTOM_TEXT
CTEXT_NONE,
CTEXT_ACTIVATE_FILESYSTEM, // Activate text ('Mount', 'Swapon', ...)
CTEXT_DEACTIVATE_FILESYSTEM, // Deactivate text ('Unmount', 'Swapoff', ...)
CTEXT_CHANGE_UUID_WARNING, // Warning to print when changing UUIDs
} ;
//struct to store file system information

View File

@ -28,6 +28,7 @@ namespace GParted
class fat16 : public FileSystem
{
public:
const Glib::ustring get_custom_text( CUSTOM_TEXT ttype, int index = 0 ) ;
FS get_filesystem_support() ;
void set_used_sectors( Partition & partition ) ;
void read_label( Partition & partition ) ;
@ -44,6 +45,8 @@ public:
const Glib::ustring & dest_part_path,
OperationDetail & operationdetail ) ;
bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
static const Glib::ustring Change_UUID_Warning [] ;
};
} //GParted

View File

@ -28,6 +28,7 @@ namespace GParted
class fat32 : public FileSystem
{
public:
const Glib::ustring get_custom_text( CUSTOM_TEXT ttype, int index = 0 ) ;
FS get_filesystem_support();
void set_used_sectors( Partition & partition ) ;
void read_label( Partition & partition ) ;
@ -44,6 +45,8 @@ public:
const Glib::ustring & dest_part_path,
OperationDetail & operationdetail ) ;
bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
const static Glib::ustring ( & Change_UUID_Warning ) [] ;
};
} //GParted

View File

@ -28,6 +28,7 @@ namespace GParted
class ntfs : public FileSystem
{
public:
const Glib::ustring get_custom_text( CUSTOM_TEXT ttype, int index = 0 ) ;
FS get_filesystem_support() ;
void set_used_sectors( Partition & partition ) ;
void read_label( Partition & partition ) ;
@ -44,6 +45,8 @@ public:
const Glib::ustring & dest_part_path,
OperationDetail & operationdetail ) ;
bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
static const Glib::ustring Change_UUID_Warning [] ;
};
} //GParted

View File

@ -1,6 +1,7 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
gparted.desktop.in.in
include/Utils.h
src/Dialog_Base_Partition.cc
src/Dialog_Disklabel.cc
src/Dialog_Partition_Copy.cc

View File

@ -1748,10 +1748,17 @@ bool GParted_Core::label_partition( const Partition & partition, OperationDetail
bool GParted_Core::change_uuid( const Partition & partition, OperationDetail & operationdetail )
{
if ( partition .uuid == UUID_RANDOM_NTFS_HALF ) {
operationdetail .add_child( OperationDetail( String::ucompose(
_("Set half of the UUID on %1 to a new, random value"),
partition .get_path()
) ) ) ;
} else {
operationdetail .add_child( OperationDetail( String::ucompose(
_("Set UUID on %1 to a new, random value"),
partition .get_path()
) ) ) ;
}
bool succes = false ;
if ( partition .type != TYPE_EXTENDED )

View File

@ -55,11 +55,19 @@ void OperationChangeUUID::apply_to_visual( std::vector<Partition> & partitions )
void OperationChangeUUID::create_description()
{
/*TO TRANSLATORS: looks like Set a new random UUID on ext4 file system on /dev/sda1 */
description = String::ucompose( _("Set a new random UUID on %1 file system on %2")
if ( partition_new .uuid == UUID_RANDOM_NTFS_HALF ) {
/*TO TRANSLATORS: looks like Set half the UUID to a new, random value on ntfs filesystem on /dev/sda1 */
description = String::ucompose( _("Set half the UUID to a new, random value on %1 filesystem on %2")
, Utils::get_filesystem_string( partition_new .filesystem )
, partition_new .get_path()
) ;
} else {
/*TO TRANSLATORS: looks like Set a new random UUID on ext4 filesystem on /dev/sda1 */
description = String::ucompose( _("Set a new random UUID on %1 filesystem on %2")
, Utils::get_filesystem_string( partition_new .filesystem )
, partition_new .get_path()
) ;
}
}
} //GParted

View File

@ -183,7 +183,7 @@ Glib::ustring Utils::get_filesystem_software( FILESYSTEM filesystem )
case FS_LINUX_SWAP : return "util-linux" ;
case FS_LVM2_PV : return "lvm2" ;
case FS_NILFS2 : return "nilfs-utils" ;
case FS_NTFS : return "ntfsprogs" ;
case FS_NTFS : return "ntfsprogs / ntfs-3g" ;
case FS_REISER4 : return "reiser4progs" ;
case FS_REISERFS : return "reiserfsprogs" ;
case FS_UFS : return "" ;

View File

@ -769,6 +769,9 @@ bool Win_GParted::Merge_Operations( unsigned int first, unsigned int second )
operations[ first ]->partition_new == operations[ second ]->partition_original
)
{
// Changing half the UUID should not override changing all of it
if ( operations[ first ]->partition_new.uuid == UUID_RANDOM_NTFS_HALF ||
operations[ second ]->partition_new.uuid == UUID_RANDOM )
operations[ first ]->partition_new.uuid = operations[ second ]->partition_new.uuid;
operations[ first ]->create_description() ;
remove_operation( second );
@ -2369,6 +2372,25 @@ void Win_GParted::activate_label_partition()
void Win_GParted::activate_change_uuid()
{
if ( gparted_core .get_filesystem_object( selected_partition .filesystem ) ->get_custom_text ( CTEXT_CHANGE_UUID_WARNING ) != "" ) {
int i ;
Gtk::MessageDialog dialog( *this
, gparted_core .get_filesystem_object( selected_partition .filesystem ) ->get_custom_text ( CTEXT_CHANGE_UUID_WARNING, 0 )
, false
, Gtk::MESSAGE_WARNING
, Gtk::BUTTONS_OK
, true
) ;
Glib::ustring tmp_msg = "" ;
for ( i = 1 ; gparted_core .get_filesystem_object( selected_partition .filesystem ) ->get_custom_text ( CTEXT_CHANGE_UUID_WARNING, i ) != "" ; i++ ) {
if ( i > 1 )
tmp_msg += "\n\n" ;
tmp_msg += gparted_core .get_filesystem_object( selected_partition .filesystem ) ->get_custom_text ( CTEXT_CHANGE_UUID_WARNING, i ) ;
}
dialog .set_secondary_text( tmp_msg ) ;
dialog .run() ;
}
//Make a duplicate of the selected partition (used in UNDO)
Partition part_temp ;
part_temp .Set( devices[ current_device ] .get_path(),
@ -2383,7 +2405,14 @@ void Win_GParted::activate_change_uuid()
false ) ;
part_temp .label = selected_partition .label ;
part_temp .uuid = _("(New UUID - will be randomly generated)") ;
if ( part_temp .filesystem == GParted::FS_NTFS )
//Explicitly ask for half, so that the user will be aware of it
//Also, keep this kind of policy out of the NTFS code.
part_temp .uuid = UUID_RANDOM_NTFS_HALF ;
else
part_temp .uuid = UUID_RANDOM ;
Operation * operation = new OperationChangeUUID( devices[ current_device ],
selected_partition, part_temp ) ;

View File

@ -29,6 +29,36 @@
namespace GParted
{
const Glib::ustring fat16::Change_UUID_Warning [] = { _( "This may invalidate your Windows Activation key."
)
, _( "On FAT and NTFS filesystems, GParted"
" uses the Volume Serial Number as UUID."
" Changing the Volume Serial Number on the Windows"
" system partition may invalidate the Windows Activation key."
)
, _( "External storage media and non-system partitions are normally safe,"
" but guarantees cannot be given."
)
, _( "Please read the manual for more information, and do not apply"
" this change if you are not prepared to re-activate Windows"
)
, ""
} ;
const Glib::ustring fat16::get_custom_text( CUSTOM_TEXT ttype, int index )
{
int i ;
switch ( ttype ) {
case CTEXT_CHANGE_UUID_WARNING :
for ( i = 0 ; i < index && Change_UUID_Warning[ i ] != "" ; i++ ) {
// Just iterate...
}
return Change_UUID_Warning [ i ] ;
default :
return FileSystem::get_custom_text( ttype, index ) ;
}
}
FS fat16::get_filesystem_support()
{
FS fs ;

View File

@ -17,6 +17,7 @@
*/
#include "../include/fat16.h"
#include "../include/fat32.h"
/*****
@ -29,6 +30,22 @@
namespace GParted
{
const Glib::ustring ( & fat32::Change_UUID_Warning ) [] = fat16::Change_UUID_Warning ;
const Glib::ustring fat32::get_custom_text( CUSTOM_TEXT ttype, int index )
{
int i ;
switch ( ttype ) {
case CTEXT_CHANGE_UUID_WARNING :
for ( i = 0 ; i < index && Change_UUID_Warning[ i ] != "" ; i++ ) {
// Just iterate...
}
return Change_UUID_Warning [ i ] ;
default :
return FileSystem::get_custom_text( ttype, index ) ;
}
}
FS fat32::get_filesystem_support()
{
FS fs ;

View File

@ -22,6 +22,38 @@
namespace GParted
{
const Glib::ustring ntfs::Change_UUID_Warning [] = { _( "This may invalidate your Windows Activation key."
)
, _( "On FAT and NTFS filesystems, GParted"
" uses the Volume Serial Number as UUID."
" Changing the Volume Serial Number on the Windows"
" system partition may invalidate the Windows Activation key."
)
, _( "External storage media and non-system partitions are normally safe."
" GParted also attempts to avoid the problem by changing only"
" half of the serial number, which should be safe as well."
" Nevertheless, guarantees cannot be given."
)
, _( "Please read the manual for more information, and do not apply"
" this change if you are not prepared to re-activate Windows"
)
, ""
} ;
const Glib::ustring ntfs::get_custom_text( CUSTOM_TEXT ttype, int index )
{
int i ;
switch ( ttype ) {
case CTEXT_CHANGE_UUID_WARNING :
for ( i = 0 ; i < index && Change_UUID_Warning[ i ] != "" ; i++ ) {
// Just iterate...
}
return Change_UUID_Warning [ i ] ;
default :
return FileSystem::get_custom_text( ttype, index ) ;
}
}
FS ntfs::get_filesystem_support()
{
FS fs ;
@ -34,8 +66,21 @@ FS ntfs::get_filesystem_support()
}
if ( ! Glib::find_program_in_path( "ntfslabel" ) .empty() ) {
Glib::ustring version ;
fs .read_label = FS::EXTERNAL ;
fs .write_label = FS::EXTERNAL ;
//Not all versions of ntfslabel support setting the Volume Serial Number
//The advanced (AR) release does as of the first 2012 release
//The stable release does not have it yet, at the time of this writing
//So: check for the presence of the command-line option.
//ntfslabel --help exits with non-zero error code (1)
Utils::execute_command( "ntfslabel --help ", output, error, false ) ;
if ( ! ( version = Utils::regexp_label( output, "--new-serial[[:blank:]]" ) ) .empty() )
fs .write_uuid = FS::EXTERNAL ;
}
if ( ! Glib::find_program_in_path( "mkntfs" ) .empty() )
@ -110,6 +155,11 @@ void ntfs::read_uuid( Partition & partition )
bool ntfs::write_uuid( const Partition & partition, OperationDetail & operationdetail )
{
if ( partition .uuid == UUID_RANDOM_NTFS_HALF )
return ! execute_command( "ntfslabel --new-half-serial " + partition .get_path(), operationdetail ) ;
else
return ! execute_command( "ntfslabel --new-serial " + partition .get_path(), operationdetail ) ;
return true ;
}