diff --git a/README b/README index 1c41500a..3b21d16a 100644 --- a/README +++ b/README @@ -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 diff --git a/help/C/gparted.xml b/help/C/gparted.xml index ffc88fd8..1ed67dec 100644 --- a/help/C/gparted.xml +++ b/help/C/gparted.xml @@ -268,7 +268,7 @@ On startup, &app; will scan your computer for disk devices. - + @@ -1044,6 +1044,11 @@ the partition when mounting the partition. + Note that using UUIDs is not a panacea. See + for + more information. + + Changes in a device name might adversely affect the following files: @@ -1141,13 +1146,187 @@ Choose: Partition - New UUID. - The application displays the set a new random UUID - operation in the Operations Pending - pane. + New UUID. + The application displays the set a new random UUID + operation in the Operations Pending + pane. + + + 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. + + + Please read (one of) the following sections for more information + if this may be a concern. + + + + + For FAT and NTFS filesystems, what GParted names, and treats as, the + UUID, is in fact its Volume Serial Number. + + + An NTFS filesystem also has a real UUID, but that is a different number, + which cannot and should not be changed - at all. + + + + UUIDs in Linux + + 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 only + identified using their UUID. Making changes to partitions may therefore + affect the Linux boot process in different ways: + + + + + When copying a partition + + + 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. + + + 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. + + + 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. + + + + + When changing the UUID of a partition + + + 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. + + + 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. + + + Before changing UUIDs of Windows partitions, please be sure to + read . + + + + + + + + UUIDs in Windows + + On NTFS and FAT filesystems, the number that GParted names, and treats as + UUID, is in fact the Volume Serial Number. + + + + 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. + + + 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. + + + + 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. + + + + + UUIDs on Windows system partitions + + + On Windows, the Volume Serial Number of the System partition is + usually used + + In atypical cases, the Volume Serial Number of another partition might + be the one that is used instead. + + + for Windows Product Activation (WPA). The first modification of this number will + count as a change for WPA. Subsequent modifications are 'free'. + + + 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. + + + 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. + + + 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. + + + As long as a partition having the original Volume Serial + Number is present at Windows boot time, WPA requirements should normally be + satisfied, and no WPA change should be noted by Windows. + + + + + + + UUIDs on data partitions + + + 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. + + + + + + + UUIDs on external storage media + + + 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. + + + + + + diff --git a/include/Utils.h b/include/Utils.h index 121f7e02..2d53f4fd 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -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 diff --git a/include/fat16.h b/include/fat16.h index d010a6cc..7d9203bb 100644 --- a/include/fat16.h +++ b/include/fat16.h @@ -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 diff --git a/include/fat32.h b/include/fat32.h index bce0eee7..8839ad54 100644 --- a/include/fat32.h +++ b/include/fat32.h @@ -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 diff --git a/include/ntfs.h b/include/ntfs.h index 0274e180..6101c8be 100644 --- a/include/ntfs.h +++ b/include/ntfs.h @@ -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 diff --git a/po/POTFILES.in b/po/POTFILES.in index 21b2ec31..12810ce1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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 diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index 413527af..9d6ceb81 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -1748,10 +1748,17 @@ bool GParted_Core::label_partition( const Partition & partition, OperationDetail bool GParted_Core::change_uuid( const Partition & partition, OperationDetail & operationdetail ) { - operationdetail .add_child( OperationDetail( String::ucompose( - _("Set UUID on %1 to a new, random value"), - partition .get_path() - ) ) ) ; + 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 ) diff --git a/src/OperationChangeUUID.cc b/src/OperationChangeUUID.cc index 25e5a61b..270852a8 100644 --- a/src/OperationChangeUUID.cc +++ b/src/OperationChangeUUID.cc @@ -55,11 +55,19 @@ void OperationChangeUUID::apply_to_visual( std::vector & 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") - , Utils::get_filesystem_string( partition_new .filesystem ) - , partition_new .get_path() - ) ; + 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 diff --git a/src/Utils.cc b/src/Utils.cc index e2152011..6413925c 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -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 "" ; diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc index dead3e90..2706c1bf 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -769,7 +769,10 @@ bool Win_GParted::Merge_Operations( unsigned int first, unsigned int second ) operations[ first ]->partition_new == operations[ second ]->partition_original ) { - operations[ first ]->partition_new.uuid = operations[ second ]->partition_new.uuid; + // 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 ) ; diff --git a/src/fat16.cc b/src/fat16.cc index b510af9a..6e4ba441 100644 --- a/src/fat16.cc +++ b/src/fat16.cc @@ -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 ; diff --git a/src/fat32.cc b/src/fat32.cc index 72080f49..db479f29 100644 --- a/src/fat32.cc +++ b/src/fat32.cc @@ -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 ; diff --git a/src/ntfs.cc b/src/ntfs.cc index 7223cb5e..3d93c257 100644 --- a/src/ntfs.cc +++ b/src/ntfs.cc @@ -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 ; }