diff -Nru libblockdev-2.14/configure.ac libblockdev-2.16/configure.ac --- libblockdev-2.14/configure.ac 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/configure.ac 2018-02-08 11:10:41.000000000 +0000 @@ -1,6 +1,6 @@ # configure.ac for libblockdev -AC_INIT([libblockdev], [2.14], [vpodzime@redhat.com]) +AC_INIT([libblockdev], [2.16], [vpodzime@redhat.com]) # Disable building static libraries. # This needs to be set before initializing automake @@ -18,6 +18,7 @@ AC_CONFIG_FILES([Makefile src/Makefile \ src/plugins/Makefile \ + src/plugins/fs/Makefile \ src/utils/Makefile \ src/utils/blockdev-utils.pc \ src/lib/Makefile \ @@ -148,6 +149,7 @@ LIBBLOCKDEV_PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.42.2]) LIBBLOCKDEV_PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.42.2]) LIBBLOCKDEV_PKG_CHECK_MODULES([UDEV], [libudev >= 216]) +LIBBLOCKDEV_PKG_CHECK_MODULES([KMOD], [libkmod >= 19]) AS_IF([test "x$with_crypto" != "xno"], [LIBBLOCKDEV_PKG_CHECK_MODULES([CRYPTSETUP], [libcryptsetup >= 1.6.7]) @@ -164,11 +166,6 @@ [LIBBLOCKDEV_CHECK_HEADER([dmraid/dmraid.h], [], [dmraid.h not available])], []) -AS_IF([test "x$with_kbd" != "xno"], - [LIBBLOCKDEV_PKG_CHECK_MODULES([KMOD], [libkmod >= 19])], - []) - - AS_IF([test "x$with_part" != "xno" -o "x$with_fs" != "xno"], [LIBBLOCKDEV_PKG_CHECK_MODULES([PARTED], [libparted >= 3.1])] []) diff -Nru libblockdev-2.14/debian/changelog libblockdev-2.16/debian/changelog --- libblockdev-2.14/debian/changelog 2017-12-13 14:29:43.000000000 +0000 +++ libblockdev-2.16/debian/changelog 2018-02-20 12:44:30.000000000 +0000 @@ -1,3 +1,24 @@ +libblockdev (2.16-2) unstable; urgency=high + + * debian/libblockdev2.symbols: Add s390x-specific symbols + + -- Jeremy Bicha Tue, 20 Feb 2018 07:44:30 -0500 + +libblockdev (2.16-1) unstable; urgency=medium + + * Team upload + + [ Jeremy Bicha ] + * New upstream release + * Add Multi-Arch: same to -dev packages, thanks multiarch hinter + * Add symbols files + * Update Vcs fields for migration to https://salsa.debian.org/ + + [ Andreas Henriksson ] + * Make libblockdev-fs2 depend on e2fsprogs (Closes: #887270) + + -- Jeremy Bicha Mon, 19 Feb 2018 19:15:55 -0500 + libblockdev (2.14-3) unstable; urgency=medium * Team upload diff -Nru libblockdev-2.14/debian/control libblockdev-2.16/debian/control --- libblockdev-2.14/debian/control 2017-12-13 14:29:43.000000000 +0000 +++ libblockdev-2.16/debian/control 2018-02-20 12:44:30.000000000 +0000 @@ -26,12 +26,11 @@ gobject-introspection, pylint, Standards-Version: 4.1.1 +Vcs-Browser: https://salsa.debian.org/utopia-team/libblockdev +Vcs-Git: https://salsa.debian.org/utopia-team/libblockdev.git Homepage: https://github.com/storaged-project/libblockdev -Vcs-Git: https://anonscm.debian.org/git/pkg-utopia/libblockdev.git -Vcs-Browser: https://anonscm.debian.org/git/pkg-utopia/libblockdev.git Package: libblockdev2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends} @@ -49,6 +48,7 @@ Package: libblockdev-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev2 (= ${binary:Version}), gir1.2-blockdev-2.0 (= ${binary:Version}), ${misc:Depends} @@ -65,8 +65,7 @@ Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} -Depends: ${shlibs:Depends}, - ${misc:Depends}, +Depends: ${misc:Depends}, ${gir:Depends} Description: libblockdev introspection data This package contains the GObject introspection data of libblockdev in @@ -78,14 +77,12 @@ Depends: libblockdev2 (>= ${source:Version}), libblockdev2 (<< ${source:Version}.1~), ${python3:Depends}, - ${shlibs:Depends}, ${misc:Depends} Description: Python 3 gobject-introspection bindings for libblockdev This package contains enhancements to the gobject-introspection bindings for libblockdev in Python3. Package: libblockdev-utils2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -97,6 +94,7 @@ Package: libblockdev-utils-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-utils2 (= ${binary:Version}), libglib2.0-dev, ${misc:Depends} @@ -105,7 +103,6 @@ with the libblockdev-utils library. Package: libblockdev-part-err2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -117,6 +114,7 @@ Package: libblockdev-part-err-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-part-err2 (= ${binary:Version}), libglib2.0-dev, ${misc:Depends} @@ -125,7 +123,6 @@ with the libblockdev-part-err library. Package: libblockdev-btrfs2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -138,6 +135,7 @@ Package: libblockdev-btrfs-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-btrfs2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -147,7 +145,6 @@ libblockdev-btrfs plugin/library. Package: libblockdev-crypto2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -159,6 +156,7 @@ Package: libblockdev-crypto-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-crypto2 (= ${binary:Version}), libglib2.0-dev, ${misc:Depends} @@ -167,7 +165,6 @@ with the libblockdev-crypto plugin/library. Package: libblockdev-dm2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -181,6 +178,7 @@ Package: libblockdev-dm-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-dm2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -193,10 +191,9 @@ with the libblockdev-dm plugin/library. Package: libblockdev-fs2 -Section: libs Architecture: any Multi-Arch: same -Depends: ${misc:Depends}, ${shlibs:Depends} +Depends: ${misc:Depends}, ${shlibs:Depends}, e2fsprogs Description: file system plugin for libblockdev The libblockdev library plugin (and in the same time a standalone library) providing the functionality related to operations with file systems. @@ -204,6 +201,7 @@ Package: libblockdev-fs-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-fs2 (= ${binary:Version}), libparted-dev, libmount-dev, @@ -214,7 +212,6 @@ with the libblockdev-fs plugin/library. Package: libblockdev-kbd2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -228,6 +225,7 @@ Package: libblockdev-kbd-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-kbd2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -237,7 +235,6 @@ with the libblockdev-kbd plugin/library. Package: libblockdev-loop2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends} @@ -248,6 +245,7 @@ Package: libblockdev-loop-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-loop2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -257,7 +255,6 @@ with the libblockdev-loop plugin/library. Package: libblockdev-lvm2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -271,6 +268,7 @@ Package: libblockdev-lvm-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-lvm2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -280,7 +278,6 @@ with the libblockdev-lvm plugin/library. Package: libblockdev-lvm-dbus2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -292,6 +289,7 @@ Package: libblockdev-lvm-dbus-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-lvm-dbus2 (= ${binary:Version}), ${misc:Depends} Description: LVM DBus plugin for libblockdev - development @@ -299,7 +297,6 @@ with the libblockdev-lvm plugin/library. Package: libblockdev-mdraid2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -312,6 +309,7 @@ Package: libblockdev-mdraid-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-mdraid2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -321,7 +319,6 @@ with the libblockdev-mdraid plugin/library. Package: libblockdev-mpath2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -334,6 +331,7 @@ Package: libblockdev-mpath-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-mpath2 (= ${binary:Version}), libblockdev-utils-dev (= ${binary:Version}), libglib2.0-dev, @@ -343,7 +341,6 @@ with the libblockdev-mpath plugin/library. Package: libblockdev-part2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -357,6 +354,7 @@ Package: libblockdev-part-dev Section: libdevel Architecture: any +Multi-Arch: same Depends: libblockdev-part2 (= ${binary:Version}), ${misc:Depends} Description: Partitioning plugin for libblockdev - development @@ -364,7 +362,6 @@ with the libblockdev-part plugin/library. Package: libblockdev-swap2 -Section: libs Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, @@ -389,8 +386,8 @@ # Package: libblockdev-s390-dev Package: libblockdev-plugins-all -Section: libs Architecture: any +Multi-Arch: same Depends: libblockdev2 (= ${binary:Version}), libblockdev-btrfs2 (= ${binary:Version}), libblockdev-crypto2 (= ${binary:Version}), @@ -415,4 +412,4 @@ The library uses plugins (LVM, BTRFS,...) and serves as a thin wrapper around its plugins' functionality. . - This is a meta-package that depends on all libblockdev plugins. + This is a metapackage that depends on all libblockdev plugins. diff -Nru libblockdev-2.14/debian/libblockdev2.symbols libblockdev-2.16/debian/libblockdev2.symbols --- libblockdev-2.14/debian/libblockdev2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,887 @@ +libblockdev.so.2 libblockdev2 #MINVER# +* Build-Depends-Package: libblockdev-dev + _bd_btrfs_add_device@Base 2.14 + _bd_btrfs_change_label@Base 2.14 + _bd_btrfs_check@Base 2.14 + _bd_btrfs_create_snapshot@Base 2.14 + _bd_btrfs_create_subvolume@Base 2.14 + _bd_btrfs_create_volume@Base 2.14 + _bd_btrfs_delete_subvolume@Base 2.14 + _bd_btrfs_filesystem_info@Base 2.14 + _bd_btrfs_get_default_subvolume_id@Base 2.14 + _bd_btrfs_is_tech_avail@Base 2.14 + _bd_btrfs_list_devices@Base 2.14 + _bd_btrfs_list_subvolumes@Base 2.14 + _bd_btrfs_mkfs@Base 2.14 + _bd_btrfs_remove_device@Base 2.14 + _bd_btrfs_repair@Base 2.14 + _bd_btrfs_resize@Base 2.14 + _bd_btrfs_set_default_subvolume@Base 2.14 + _bd_crypto_device_is_luks@Base 2.14 + _bd_crypto_escrow_device@Base 2.14 + _bd_crypto_generate_backup_passphrase@Base 2.14 + _bd_crypto_is_tech_avail@Base 2.14 + _bd_crypto_luks_add_key@Base 2.14 + _bd_crypto_luks_add_key_blob@Base 2.14 + _bd_crypto_luks_change_key@Base 2.14 + _bd_crypto_luks_change_key_blob@Base 2.14 + _bd_crypto_luks_close@Base 2.14 + _bd_crypto_luks_format@Base 2.14 + _bd_crypto_luks_format_blob@Base 2.14 + _bd_crypto_luks_open@Base 2.14 + _bd_crypto_luks_open_blob@Base 2.14 + _bd_crypto_luks_remove_key@Base 2.14 + _bd_crypto_luks_remove_key_blob@Base 2.14 + _bd_crypto_luks_resize@Base 2.14 + _bd_crypto_luks_status@Base 2.14 + _bd_crypto_luks_uuid@Base 2.14 + _bd_crypto_tc_close@Base 2.14 + _bd_crypto_tc_open@Base 2.14 + _bd_dm_activate_raid_set@Base 2.14 + _bd_dm_create_linear@Base 2.14 + _bd_dm_deactivate_raid_set@Base 2.14 + _bd_dm_get_member_raid_sets@Base 2.14 + _bd_dm_get_raid_set_type@Base 2.14 + _bd_dm_get_subsystem_from_name@Base 2.14 + _bd_dm_is_tech_avail@Base 2.14 + _bd_dm_map_exists@Base 2.14 + _bd_dm_name_from_node@Base 2.14 + _bd_dm_node_from_name@Base 2.14 + _bd_dm_remove@Base 2.14 + _bd_fs_can_check@Base 2.14 + _bd_fs_can_repair@Base 2.14 + _bd_fs_can_resize@Base 2.14 + _bd_fs_can_set_label@Base 2.14 + _bd_fs_check@Base 2.14 + _bd_fs_clean@Base 2.14 + _bd_fs_ext2_check@Base 2.14 + _bd_fs_ext2_get_info@Base 2.14 + _bd_fs_ext2_mkfs@Base 2.14 + _bd_fs_ext2_repair@Base 2.14 + _bd_fs_ext2_resize@Base 2.14 + _bd_fs_ext2_set_label@Base 2.14 + _bd_fs_ext2_wipe@Base 2.14 + _bd_fs_ext3_check@Base 2.14 + _bd_fs_ext3_get_info@Base 2.14 + _bd_fs_ext3_mkfs@Base 2.14 + _bd_fs_ext3_repair@Base 2.14 + _bd_fs_ext3_resize@Base 2.14 + _bd_fs_ext3_set_label@Base 2.14 + _bd_fs_ext3_wipe@Base 2.14 + _bd_fs_ext4_check@Base 2.14 + _bd_fs_ext4_get_info@Base 2.14 + _bd_fs_ext4_mkfs@Base 2.14 + _bd_fs_ext4_repair@Base 2.14 + _bd_fs_ext4_resize@Base 2.14 + _bd_fs_ext4_set_label@Base 2.14 + _bd_fs_ext4_wipe@Base 2.14 + _bd_fs_get_fstype@Base 2.14 + _bd_fs_get_mountpoint@Base 2.14 + _bd_fs_is_tech_avail@Base 2.14 + _bd_fs_mount@Base 2.14 + _bd_fs_ntfs_check@Base 2.14 + _bd_fs_ntfs_get_info@Base 2.14 + _bd_fs_ntfs_mkfs@Base 2.14 + _bd_fs_ntfs_repair@Base 2.14 + _bd_fs_ntfs_resize@Base 2.14 + _bd_fs_ntfs_set_label@Base 2.14 + _bd_fs_ntfs_wipe@Base 2.14 + _bd_fs_repair@Base 2.14 + _bd_fs_resize@Base 2.14 + _bd_fs_set_label@Base 2.14 + _bd_fs_unmount@Base 2.14 + _bd_fs_vfat_check@Base 2.14 + _bd_fs_vfat_get_info@Base 2.14 + _bd_fs_vfat_mkfs@Base 2.14 + _bd_fs_vfat_repair@Base 2.14 + _bd_fs_vfat_resize@Base 2.14 + _bd_fs_vfat_set_label@Base 2.14 + _bd_fs_vfat_wipe@Base 2.14 + _bd_fs_wipe@Base 2.14 + _bd_fs_xfs_check@Base 2.14 + _bd_fs_xfs_get_info@Base 2.14 + _bd_fs_xfs_mkfs@Base 2.14 + _bd_fs_xfs_repair@Base 2.14 + _bd_fs_xfs_resize@Base 2.14 + _bd_fs_xfs_set_label@Base 2.14 + _bd_fs_xfs_wipe@Base 2.14 + _bd_kbd_bcache_attach@Base 2.14 + _bd_kbd_bcache_create@Base 2.14 + _bd_kbd_bcache_destroy@Base 2.14 + _bd_kbd_bcache_detach@Base 2.14 + _bd_kbd_bcache_get_backing_device@Base 2.14 + _bd_kbd_bcache_get_cache_device@Base 2.14 + _bd_kbd_bcache_get_mode@Base 2.14 + _bd_kbd_bcache_get_mode_from_str@Base 2.14 + _bd_kbd_bcache_get_mode_str@Base 2.14 + _bd_kbd_bcache_set_mode@Base 2.14 + _bd_kbd_bcache_status@Base 2.14 + _bd_kbd_is_tech_avail@Base 2.14 + _bd_kbd_zram_add_device@Base 2.14 + _bd_kbd_zram_create_devices@Base 2.14 + _bd_kbd_zram_destroy_devices@Base 2.14 + _bd_kbd_zram_get_stats@Base 2.14 + _bd_kbd_zram_remove_device@Base 2.14 + _bd_loop_get_autoclear@Base 2.14 + _bd_loop_get_backing_file@Base 2.14 + _bd_loop_get_loop_name@Base 2.14 + _bd_loop_is_tech_avail@Base 2.14 + _bd_loop_set_autoclear@Base 2.14 + _bd_loop_setup@Base 2.14 + _bd_loop_setup_from_fd@Base 2.14 + _bd_loop_teardown@Base 2.14 + _bd_lvm_cache_attach@Base 2.14 + _bd_lvm_cache_create_cached_lv@Base 2.14 + _bd_lvm_cache_create_pool@Base 2.14 + _bd_lvm_cache_detach@Base 2.14 + _bd_lvm_cache_get_default_md_size@Base 2.14 + _bd_lvm_cache_get_mode_from_str@Base 2.14 + _bd_lvm_cache_get_mode_str@Base 2.14 + _bd_lvm_cache_pool_convert@Base 2.14 + _bd_lvm_cache_pool_name@Base 2.14 + _bd_lvm_cache_stats@Base 2.14 + _bd_lvm_data_lv_name@Base 2.14 + _bd_lvm_get_global_config@Base 2.14 + _bd_lvm_get_lv_physical_size@Base 2.14 + _bd_lvm_get_max_lv_size@Base 2.14 + _bd_lvm_get_supported_pe_sizes@Base 2.14 + _bd_lvm_get_thpool_meta_size@Base 2.14 + _bd_lvm_get_thpool_padding@Base 2.14 + _bd_lvm_is_supported_pe_size@Base 2.14 + _bd_lvm_is_tech_avail@Base 2.14 + _bd_lvm_is_valid_thpool_chunk_size@Base 2.14 + _bd_lvm_is_valid_thpool_md_size@Base 2.14 + _bd_lvm_lvactivate@Base 2.14 + _bd_lvm_lvcreate@Base 2.14 + _bd_lvm_lvdeactivate@Base 2.14 + _bd_lvm_lvinfo@Base 2.14 + _bd_lvm_lvorigin@Base 2.14 + _bd_lvm_lvremove@Base 2.14 + _bd_lvm_lvrename@Base 2.14 + _bd_lvm_lvresize@Base 2.14 + _bd_lvm_lvs@Base 2.14 + _bd_lvm_lvsnapshotcreate@Base 2.14 + _bd_lvm_lvsnapshotmerge@Base 2.14 + _bd_lvm_metadata_lv_name@Base 2.14 + _bd_lvm_pvcreate@Base 2.14 + _bd_lvm_pvinfo@Base 2.14 + _bd_lvm_pvmove@Base 2.14 + _bd_lvm_pvremove@Base 2.14 + _bd_lvm_pvresize@Base 2.14 + _bd_lvm_pvs@Base 2.14 + _bd_lvm_pvscan@Base 2.14 + _bd_lvm_round_size_to_pe@Base 2.14 + _bd_lvm_set_global_config@Base 2.14 + _bd_lvm_thlvcreate@Base 2.14 + _bd_lvm_thlvpoolname@Base 2.14 + _bd_lvm_thpool_convert@Base 2.14 + _bd_lvm_thpoolcreate@Base 2.14 + _bd_lvm_thsnapshotcreate@Base 2.14 + _bd_lvm_vgactivate@Base 2.14 + _bd_lvm_vgcreate@Base 2.14 + _bd_lvm_vgdeactivate@Base 2.14 + _bd_lvm_vgextend@Base 2.14 + _bd_lvm_vginfo@Base 2.14 + _bd_lvm_vgreduce@Base 2.14 + _bd_lvm_vgremove@Base 2.14 + _bd_lvm_vgrename@Base 2.14 + _bd_lvm_vgs@Base 2.14 + _bd_md_activate@Base 2.14 + _bd_md_add@Base 2.14 + _bd_md_canonicalize_uuid@Base 2.14 + _bd_md_create@Base 2.14 + _bd_md_deactivate@Base 2.14 + _bd_md_denominate@Base 2.14 + _bd_md_destroy@Base 2.14 + _bd_md_detail@Base 2.14 + _bd_md_examine@Base 2.14 + _bd_md_get_bitmap_location@Base 2.14 + _bd_md_get_md_uuid@Base 2.14 + _bd_md_get_status@Base 2.14 + _bd_md_get_superblock_size@Base 2.14 + _bd_md_is_tech_avail@Base 2.14 + _bd_md_name_from_node@Base 2.14 + _bd_md_node_from_name@Base 2.14 + _bd_md_nominate@Base 2.14 + _bd_md_remove@Base 2.14 + _bd_md_request_sync_action@Base 2.14 + _bd_md_run@Base 2.14 + _bd_md_set_bitmap_location@Base 2.14 + _bd_mpath_flush_mpaths@Base 2.14 + _bd_mpath_get_mpath_members@Base 2.14 + _bd_mpath_is_mpath_member@Base 2.14 + _bd_mpath_is_tech_avail@Base 2.14 + _bd_mpath_set_friendly_names@Base 2.14 + _bd_part_create_part@Base 2.14 + _bd_part_create_table@Base 2.14 + _bd_part_delete_part@Base 2.14 + _bd_part_get_best_free_region@Base 2.14 + _bd_part_get_disk_free_regions@Base 2.14 + _bd_part_get_disk_parts@Base 2.14 + _bd_part_get_disk_spec@Base 2.14 + _bd_part_get_flag_str@Base 2.14 + _bd_part_get_part_by_pos@Base 2.14 + _bd_part_get_part_id@Base 2.14 + _bd_part_get_part_spec@Base 2.14 + _bd_part_get_part_table_type_str@Base 2.14 + _bd_part_get_type_str@Base 2.14 + _bd_part_is_tech_avail@Base 2.14 + _bd_part_resize_part@Base 2.14 + _bd_part_set_disk_flag@Base 2.14 + _bd_part_set_part_flag@Base 2.14 + _bd_part_set_part_flags@Base 2.14 + _bd_part_set_part_id@Base 2.14 + _bd_part_set_part_name@Base 2.14 + _bd_part_set_part_type@Base 2.14 + (arch=s390x)_bd_s390_dasd_format@Base 2.14 + (arch=s390x)_bd_s390_dasd_is_fba@Base 2.14 + (arch=s390x)_bd_s390_dasd_is_ldl@Base 2.14 + (arch=s390x)_bd_s390_dasd_needs_format@Base 2.14 + (arch=s390x)_bd_s390_dasd_online@Base 2.14 + (arch=s390x)_bd_s390_is_tech_avail@Base 2.14 + (arch=s390x)_bd_s390_sanitize_dev_input@Base 2.14 + (arch=s390x)_bd_s390_zfcp_offline@Base 2.14 + (arch=s390x)_bd_s390_zfcp_online@Base 2.14 + (arch=s390x)_bd_s390_zfcp_sanitize_lun_input@Base 2.14 + (arch=s390x)_bd_s390_zfcp_sanitize_wwpn_input@Base 2.14 + (arch=s390x)_bd_s390_zfcp_scsi_offline@Base 2.14 + _bd_swap_is_tech_avail@Base 2.14 + _bd_swap_mkswap@Base 2.14 + _bd_swap_set_label@Base 2.14 + _bd_swap_swapoff@Base 2.14 + _bd_swap_swapon@Base 2.14 + _bd_swap_swapstatus@Base 2.14 + bd_btrfs_add_device@Base 2.14 + bd_btrfs_add_device_stub@Base 2.14 + bd_btrfs_change_label@Base 2.14 + bd_btrfs_change_label_stub@Base 2.14 + bd_btrfs_check@Base 2.14 + bd_btrfs_check_stub@Base 2.14 + bd_btrfs_create_snapshot@Base 2.14 + bd_btrfs_create_snapshot_stub@Base 2.14 + bd_btrfs_create_subvolume@Base 2.14 + bd_btrfs_create_subvolume_stub@Base 2.14 + bd_btrfs_create_volume@Base 2.14 + bd_btrfs_create_volume_stub@Base 2.14 + bd_btrfs_delete_subvolume@Base 2.14 + bd_btrfs_delete_subvolume_stub@Base 2.14 + bd_btrfs_device_info_copy@Base 2.14 + bd_btrfs_device_info_free@Base 2.14 + bd_btrfs_device_info_get_type@Base 2.14 + bd_btrfs_error_quark@Base 2.14 + bd_btrfs_filesystem_info@Base 2.14 + bd_btrfs_filesystem_info_copy@Base 2.14 + bd_btrfs_filesystem_info_free@Base 2.14 + bd_btrfs_filesystem_info_get_type@Base 2.14 + bd_btrfs_filesystem_info_stub@Base 2.14 + bd_btrfs_get_default_subvolume_id@Base 2.14 + bd_btrfs_get_default_subvolume_id_stub@Base 2.14 + bd_btrfs_is_tech_avail@Base 2.14 + bd_btrfs_is_tech_avail_stub@Base 2.14 + bd_btrfs_list_devices@Base 2.14 + bd_btrfs_list_devices_stub@Base 2.14 + bd_btrfs_list_subvolumes@Base 2.14 + bd_btrfs_list_subvolumes_stub@Base 2.14 + bd_btrfs_mkfs@Base 2.14 + bd_btrfs_mkfs_stub@Base 2.14 + bd_btrfs_remove_device@Base 2.14 + bd_btrfs_remove_device_stub@Base 2.14 + bd_btrfs_repair@Base 2.14 + bd_btrfs_repair_stub@Base 2.14 + bd_btrfs_resize@Base 2.14 + bd_btrfs_resize_stub@Base 2.14 + bd_btrfs_set_default_subvolume@Base 2.14 + bd_btrfs_set_default_subvolume_stub@Base 2.14 + bd_btrfs_subvolume_info_copy@Base 2.14 + bd_btrfs_subvolume_info_free@Base 2.14 + bd_btrfs_subvolume_info_get_type@Base 2.14 + bd_crypto_device_is_luks@Base 2.14 + bd_crypto_device_is_luks_stub@Base 2.14 + bd_crypto_error_quark@Base 2.14 + bd_crypto_escrow_device@Base 2.14 + bd_crypto_escrow_device_stub@Base 2.14 + bd_crypto_generate_backup_passphrase@Base 2.14 + bd_crypto_generate_backup_passphrase_stub@Base 2.14 + bd_crypto_is_tech_avail@Base 2.14 + bd_crypto_is_tech_avail_stub@Base 2.14 + bd_crypto_luks_add_key@Base 2.14 + bd_crypto_luks_add_key_blob@Base 2.14 + bd_crypto_luks_add_key_blob_stub@Base 2.14 + bd_crypto_luks_add_key_stub@Base 2.14 + bd_crypto_luks_change_key@Base 2.14 + bd_crypto_luks_change_key_blob@Base 2.14 + bd_crypto_luks_change_key_blob_stub@Base 2.14 + bd_crypto_luks_change_key_stub@Base 2.14 + bd_crypto_luks_close@Base 2.14 + bd_crypto_luks_close_stub@Base 2.14 + bd_crypto_luks_format@Base 2.14 + bd_crypto_luks_format_blob@Base 2.14 + bd_crypto_luks_format_blob_stub@Base 2.14 + bd_crypto_luks_format_stub@Base 2.14 + bd_crypto_luks_open@Base 2.14 + bd_crypto_luks_open_blob@Base 2.14 + bd_crypto_luks_open_blob_stub@Base 2.14 + bd_crypto_luks_open_stub@Base 2.14 + bd_crypto_luks_remove_key@Base 2.14 + bd_crypto_luks_remove_key_blob@Base 2.14 + bd_crypto_luks_remove_key_blob_stub@Base 2.14 + bd_crypto_luks_remove_key_stub@Base 2.14 + bd_crypto_luks_resize@Base 2.14 + bd_crypto_luks_resize_stub@Base 2.14 + bd_crypto_luks_status@Base 2.14 + bd_crypto_luks_status_stub@Base 2.14 + bd_crypto_luks_uuid@Base 2.14 + bd_crypto_luks_uuid_stub@Base 2.14 + bd_crypto_tc_close@Base 2.14 + bd_crypto_tc_close_stub@Base 2.14 + bd_crypto_tc_open@Base 2.14 + bd_crypto_tc_open_stub@Base 2.14 + bd_dm_activate_raid_set@Base 2.14 + bd_dm_activate_raid_set_stub@Base 2.14 + bd_dm_create_linear@Base 2.14 + bd_dm_create_linear_stub@Base 2.14 + bd_dm_deactivate_raid_set@Base 2.14 + bd_dm_deactivate_raid_set_stub@Base 2.14 + bd_dm_error_quark@Base 2.14 + bd_dm_get_member_raid_sets@Base 2.14 + bd_dm_get_member_raid_sets_stub@Base 2.14 + bd_dm_get_raid_set_type@Base 2.14 + bd_dm_get_raid_set_type_stub@Base 2.14 + bd_dm_get_subsystem_from_name@Base 2.14 + bd_dm_get_subsystem_from_name_stub@Base 2.14 + bd_dm_is_tech_avail@Base 2.14 + bd_dm_is_tech_avail_stub@Base 2.14 + bd_dm_map_exists@Base 2.14 + bd_dm_map_exists_stub@Base 2.14 + bd_dm_name_from_node@Base 2.14 + bd_dm_name_from_node_stub@Base 2.14 + bd_dm_node_from_name@Base 2.14 + bd_dm_node_from_name_stub@Base 2.14 + bd_dm_remove@Base 2.14 + bd_dm_remove_stub@Base 2.14 + bd_ensure_init@Base 2.14 + bd_fs_can_check@Base 2.14 + bd_fs_can_check_stub@Base 2.14 + bd_fs_can_repair@Base 2.14 + bd_fs_can_repair_stub@Base 2.14 + bd_fs_can_resize@Base 2.14 + bd_fs_can_resize_stub@Base 2.14 + bd_fs_can_set_label@Base 2.14 + bd_fs_can_set_label_stub@Base 2.14 + bd_fs_check@Base 2.14 + bd_fs_check_stub@Base 2.14 + bd_fs_clean@Base 2.14 + bd_fs_clean_stub@Base 2.14 + bd_fs_error_quark@Base 2.14 + bd_fs_ext2_check@Base 2.14 + bd_fs_ext2_check_stub@Base 2.14 + bd_fs_ext2_get_info@Base 2.14 + bd_fs_ext2_get_info_stub@Base 2.14 + bd_fs_ext2_info_copy@Base 2.14 + bd_fs_ext2_info_free@Base 2.14 + bd_fs_ext2_info_get_type@Base 2.14 + bd_fs_ext2_mkfs@Base 2.14 + bd_fs_ext2_mkfs_stub@Base 2.14 + bd_fs_ext2_repair@Base 2.14 + bd_fs_ext2_repair_stub@Base 2.14 + bd_fs_ext2_resize@Base 2.14 + bd_fs_ext2_resize_stub@Base 2.14 + bd_fs_ext2_set_label@Base 2.14 + bd_fs_ext2_set_label_stub@Base 2.14 + bd_fs_ext2_wipe@Base 2.14 + bd_fs_ext2_wipe_stub@Base 2.14 + bd_fs_ext3_check@Base 2.14 + bd_fs_ext3_check_stub@Base 2.14 + bd_fs_ext3_get_info@Base 2.14 + bd_fs_ext3_get_info_stub@Base 2.14 + bd_fs_ext3_info_copy@Base 2.14 + bd_fs_ext3_info_free@Base 2.14 + bd_fs_ext3_info_get_type@Base 2.14 + bd_fs_ext3_mkfs@Base 2.14 + bd_fs_ext3_mkfs_stub@Base 2.14 + bd_fs_ext3_repair@Base 2.14 + bd_fs_ext3_repair_stub@Base 2.14 + bd_fs_ext3_resize@Base 2.14 + bd_fs_ext3_resize_stub@Base 2.14 + bd_fs_ext3_set_label@Base 2.14 + bd_fs_ext3_set_label_stub@Base 2.14 + bd_fs_ext3_wipe@Base 2.14 + bd_fs_ext3_wipe_stub@Base 2.14 + bd_fs_ext4_check@Base 2.14 + bd_fs_ext4_check_stub@Base 2.14 + bd_fs_ext4_get_info@Base 2.14 + bd_fs_ext4_get_info_stub@Base 2.14 + bd_fs_ext4_info_copy@Base 2.14 + bd_fs_ext4_info_free@Base 2.14 + bd_fs_ext4_info_get_type@Base 2.14 + bd_fs_ext4_mkfs@Base 2.14 + bd_fs_ext4_mkfs_stub@Base 2.14 + bd_fs_ext4_repair@Base 2.14 + bd_fs_ext4_repair_stub@Base 2.14 + bd_fs_ext4_resize@Base 2.14 + bd_fs_ext4_resize_stub@Base 2.14 + bd_fs_ext4_set_label@Base 2.14 + bd_fs_ext4_set_label_stub@Base 2.14 + bd_fs_ext4_wipe@Base 2.14 + bd_fs_ext4_wipe_stub@Base 2.14 + bd_fs_get_fstype@Base 2.14 + bd_fs_get_fstype_stub@Base 2.14 + bd_fs_get_mountpoint@Base 2.14 + bd_fs_get_mountpoint_stub@Base 2.14 + bd_fs_is_tech_avail@Base 2.14 + bd_fs_is_tech_avail_stub@Base 2.14 + bd_fs_mount@Base 2.14 + bd_fs_mount_stub@Base 2.14 + bd_fs_ntfs_check@Base 2.14 + bd_fs_ntfs_check_stub@Base 2.14 + bd_fs_ntfs_get_info@Base 2.14 + bd_fs_ntfs_get_info_stub@Base 2.14 + bd_fs_ntfs_info_copy@Base 2.14 + bd_fs_ntfs_info_free@Base 2.14 + bd_fs_ntfs_info_get_type@Base 2.14 + bd_fs_ntfs_mkfs@Base 2.14 + bd_fs_ntfs_mkfs_stub@Base 2.14 + bd_fs_ntfs_repair@Base 2.14 + bd_fs_ntfs_repair_stub@Base 2.14 + bd_fs_ntfs_resize@Base 2.14 + bd_fs_ntfs_resize_stub@Base 2.14 + bd_fs_ntfs_set_label@Base 2.14 + bd_fs_ntfs_set_label_stub@Base 2.14 + bd_fs_ntfs_wipe@Base 2.14 + bd_fs_ntfs_wipe_stub@Base 2.14 + bd_fs_repair@Base 2.14 + bd_fs_repair_stub@Base 2.14 + bd_fs_resize@Base 2.14 + bd_fs_resize_stub@Base 2.14 + bd_fs_set_label@Base 2.14 + bd_fs_set_label_stub@Base 2.14 + bd_fs_unmount@Base 2.14 + bd_fs_unmount_stub@Base 2.14 + bd_fs_vfat_check@Base 2.14 + bd_fs_vfat_check_stub@Base 2.14 + bd_fs_vfat_get_info@Base 2.14 + bd_fs_vfat_get_info_stub@Base 2.14 + bd_fs_vfat_info_copy@Base 2.14 + bd_fs_vfat_info_free@Base 2.14 + bd_fs_vfat_info_get_type@Base 2.14 + bd_fs_vfat_mkfs@Base 2.14 + bd_fs_vfat_mkfs_stub@Base 2.14 + bd_fs_vfat_repair@Base 2.14 + bd_fs_vfat_repair_stub@Base 2.14 + bd_fs_vfat_resize@Base 2.14 + bd_fs_vfat_resize_stub@Base 2.14 + bd_fs_vfat_set_label@Base 2.14 + bd_fs_vfat_set_label_stub@Base 2.14 + bd_fs_vfat_wipe@Base 2.14 + bd_fs_vfat_wipe_stub@Base 2.14 + bd_fs_wipe@Base 2.14 + bd_fs_wipe_stub@Base 2.14 + bd_fs_xfs_check@Base 2.14 + bd_fs_xfs_check_stub@Base 2.14 + bd_fs_xfs_get_info@Base 2.14 + bd_fs_xfs_get_info_stub@Base 2.14 + bd_fs_xfs_info_copy@Base 2.14 + bd_fs_xfs_info_free@Base 2.14 + bd_fs_xfs_info_get_type@Base 2.14 + bd_fs_xfs_mkfs@Base 2.14 + bd_fs_xfs_mkfs_stub@Base 2.14 + bd_fs_xfs_repair@Base 2.14 + bd_fs_xfs_repair_stub@Base 2.14 + bd_fs_xfs_resize@Base 2.14 + bd_fs_xfs_resize_stub@Base 2.14 + bd_fs_xfs_set_label@Base 2.14 + bd_fs_xfs_set_label_stub@Base 2.14 + bd_fs_xfs_wipe@Base 2.14 + bd_fs_xfs_wipe_stub@Base 2.14 + bd_get_available_plugin_names@Base 2.14 + bd_get_plugin_name@Base 2.14 + bd_get_plugin_soname@Base 2.14 + bd_init@Base 2.14 + bd_init_error_quark@Base 2.14 + bd_is_initialized@Base 2.14 + bd_is_plugin_available@Base 2.14 + bd_kbd_bcache_attach@Base 2.14 + bd_kbd_bcache_attach_stub@Base 2.14 + bd_kbd_bcache_create@Base 2.14 + bd_kbd_bcache_create_stub@Base 2.14 + bd_kbd_bcache_destroy@Base 2.14 + bd_kbd_bcache_destroy_stub@Base 2.14 + bd_kbd_bcache_detach@Base 2.14 + bd_kbd_bcache_detach_stub@Base 2.14 + bd_kbd_bcache_get_backing_device@Base 2.14 + bd_kbd_bcache_get_backing_device_stub@Base 2.14 + bd_kbd_bcache_get_cache_device@Base 2.14 + bd_kbd_bcache_get_cache_device_stub@Base 2.14 + bd_kbd_bcache_get_mode@Base 2.14 + bd_kbd_bcache_get_mode_from_str@Base 2.14 + bd_kbd_bcache_get_mode_from_str_stub@Base 2.14 + bd_kbd_bcache_get_mode_str@Base 2.14 + bd_kbd_bcache_get_mode_str_stub@Base 2.14 + bd_kbd_bcache_get_mode_stub@Base 2.14 + bd_kbd_bcache_set_mode@Base 2.14 + bd_kbd_bcache_set_mode_stub@Base 2.14 + bd_kbd_bcache_stats_copy@Base 2.14 + bd_kbd_bcache_stats_free@Base 2.14 + bd_kbd_bcache_stats_get_type@Base 2.14 + bd_kbd_bcache_status@Base 2.14 + bd_kbd_bcache_status_stub@Base 2.14 + bd_kbd_error_quark@Base 2.14 + bd_kbd_is_tech_avail@Base 2.14 + bd_kbd_is_tech_avail_stub@Base 2.14 + bd_kbd_zram_add_device@Base 2.14 + bd_kbd_zram_add_device_stub@Base 2.14 + bd_kbd_zram_create_devices@Base 2.14 + bd_kbd_zram_create_devices_stub@Base 2.14 + bd_kbd_zram_destroy_devices@Base 2.14 + bd_kbd_zram_destroy_devices_stub@Base 2.14 + bd_kbd_zram_get_stats@Base 2.14 + bd_kbd_zram_get_stats_stub@Base 2.14 + bd_kbd_zram_remove_device@Base 2.14 + bd_kbd_zram_remove_device_stub@Base 2.14 + bd_kbd_zram_stats_copy@Base 2.14 + bd_kbd_zram_stats_free@Base 2.14 + bd_kbd_zram_stats_get_type@Base 2.14 + bd_loop_error_quark@Base 2.14 + bd_loop_get_autoclear@Base 2.14 + bd_loop_get_autoclear_stub@Base 2.14 + bd_loop_get_backing_file@Base 2.14 + bd_loop_get_backing_file_stub@Base 2.14 + bd_loop_get_loop_name@Base 2.14 + bd_loop_get_loop_name_stub@Base 2.14 + bd_loop_is_tech_avail@Base 2.14 + bd_loop_is_tech_avail_stub@Base 2.14 + bd_loop_set_autoclear@Base 2.14 + bd_loop_set_autoclear_stub@Base 2.14 + bd_loop_setup@Base 2.14 + bd_loop_setup_from_fd@Base 2.14 + bd_loop_setup_from_fd_stub@Base 2.14 + bd_loop_setup_stub@Base 2.14 + bd_loop_teardown@Base 2.14 + bd_loop_teardown_stub@Base 2.14 + bd_lvm_cache_attach@Base 2.14 + bd_lvm_cache_attach_stub@Base 2.14 + bd_lvm_cache_create_cached_lv@Base 2.14 + bd_lvm_cache_create_cached_lv_stub@Base 2.14 + bd_lvm_cache_create_pool@Base 2.14 + bd_lvm_cache_create_pool_stub@Base 2.14 + bd_lvm_cache_detach@Base 2.14 + bd_lvm_cache_detach_stub@Base 2.14 + bd_lvm_cache_get_default_md_size@Base 2.14 + bd_lvm_cache_get_default_md_size_stub@Base 2.14 + bd_lvm_cache_get_mode_from_str@Base 2.14 + bd_lvm_cache_get_mode_from_str_stub@Base 2.14 + bd_lvm_cache_get_mode_str@Base 2.14 + bd_lvm_cache_get_mode_str_stub@Base 2.14 + bd_lvm_cache_pool_convert@Base 2.14 + bd_lvm_cache_pool_convert_stub@Base 2.14 + bd_lvm_cache_pool_name@Base 2.14 + bd_lvm_cache_pool_name_stub@Base 2.14 + bd_lvm_cache_stats@Base 2.14 + bd_lvm_cache_stats_copy@Base 2.14 + bd_lvm_cache_stats_free@Base 2.14 + bd_lvm_cache_stats_get_type@Base 2.14 + bd_lvm_cache_stats_stub@Base 2.14 + bd_lvm_data_lv_name@Base 2.14 + bd_lvm_data_lv_name_stub@Base 2.14 + bd_lvm_error_quark@Base 2.14 + bd_lvm_get_global_config@Base 2.14 + bd_lvm_get_global_config_stub@Base 2.14 + bd_lvm_get_lv_physical_size@Base 2.14 + bd_lvm_get_lv_physical_size_stub@Base 2.14 + bd_lvm_get_max_lv_size@Base 2.14 + bd_lvm_get_max_lv_size_stub@Base 2.14 + bd_lvm_get_supported_pe_sizes@Base 2.14 + bd_lvm_get_supported_pe_sizes_stub@Base 2.14 + bd_lvm_get_thpool_meta_size@Base 2.14 + bd_lvm_get_thpool_meta_size_stub@Base 2.14 + bd_lvm_get_thpool_padding@Base 2.14 + bd_lvm_get_thpool_padding_stub@Base 2.14 + bd_lvm_is_supported_pe_size@Base 2.14 + bd_lvm_is_supported_pe_size_stub@Base 2.14 + bd_lvm_is_tech_avail@Base 2.14 + bd_lvm_is_tech_avail_stub@Base 2.14 + bd_lvm_is_valid_thpool_chunk_size@Base 2.14 + bd_lvm_is_valid_thpool_chunk_size_stub@Base 2.14 + bd_lvm_is_valid_thpool_md_size@Base 2.14 + bd_lvm_is_valid_thpool_md_size_stub@Base 2.14 + bd_lvm_lvactivate@Base 2.14 + bd_lvm_lvactivate_stub@Base 2.14 + bd_lvm_lvcreate@Base 2.14 + bd_lvm_lvcreate_stub@Base 2.14 + bd_lvm_lvdata_copy@Base 2.14 + bd_lvm_lvdata_free@Base 2.14 + bd_lvm_lvdata_get_type@Base 2.14 + bd_lvm_lvdeactivate@Base 2.14 + bd_lvm_lvdeactivate_stub@Base 2.14 + bd_lvm_lvinfo@Base 2.14 + bd_lvm_lvinfo_stub@Base 2.14 + bd_lvm_lvorigin@Base 2.14 + bd_lvm_lvorigin_stub@Base 2.14 + bd_lvm_lvremove@Base 2.14 + bd_lvm_lvremove_stub@Base 2.14 + bd_lvm_lvrename@Base 2.14 + bd_lvm_lvrename_stub@Base 2.14 + bd_lvm_lvresize@Base 2.14 + bd_lvm_lvresize_stub@Base 2.14 + bd_lvm_lvs@Base 2.14 + bd_lvm_lvs_stub@Base 2.14 + bd_lvm_lvsnapshotcreate@Base 2.14 + bd_lvm_lvsnapshotcreate_stub@Base 2.14 + bd_lvm_lvsnapshotmerge@Base 2.14 + bd_lvm_lvsnapshotmerge_stub@Base 2.14 + bd_lvm_metadata_lv_name@Base 2.14 + bd_lvm_metadata_lv_name_stub@Base 2.14 + bd_lvm_pvcreate@Base 2.14 + bd_lvm_pvcreate_stub@Base 2.14 + bd_lvm_pvdata_copy@Base 2.14 + bd_lvm_pvdata_free@Base 2.14 + bd_lvm_pvdata_get_type@Base 2.14 + bd_lvm_pvinfo@Base 2.14 + bd_lvm_pvinfo_stub@Base 2.14 + bd_lvm_pvmove@Base 2.14 + bd_lvm_pvmove_stub@Base 2.14 + bd_lvm_pvremove@Base 2.14 + bd_lvm_pvremove_stub@Base 2.14 + bd_lvm_pvresize@Base 2.14 + bd_lvm_pvresize_stub@Base 2.14 + bd_lvm_pvs@Base 2.14 + bd_lvm_pvs_stub@Base 2.14 + bd_lvm_pvscan@Base 2.14 + bd_lvm_pvscan_stub@Base 2.14 + bd_lvm_round_size_to_pe@Base 2.14 + bd_lvm_round_size_to_pe_stub@Base 2.14 + bd_lvm_set_global_config@Base 2.14 + bd_lvm_set_global_config_stub@Base 2.14 + bd_lvm_thlvcreate@Base 2.14 + bd_lvm_thlvcreate_stub@Base 2.14 + bd_lvm_thlvpoolname@Base 2.14 + bd_lvm_thlvpoolname_stub@Base 2.14 + bd_lvm_thpool_convert@Base 2.14 + bd_lvm_thpool_convert_stub@Base 2.14 + bd_lvm_thpoolcreate@Base 2.14 + bd_lvm_thpoolcreate_stub@Base 2.14 + bd_lvm_thsnapshotcreate@Base 2.14 + bd_lvm_thsnapshotcreate_stub@Base 2.14 + bd_lvm_vgactivate@Base 2.14 + bd_lvm_vgactivate_stub@Base 2.14 + bd_lvm_vgcreate@Base 2.14 + bd_lvm_vgcreate_stub@Base 2.14 + bd_lvm_vgdata_copy@Base 2.14 + bd_lvm_vgdata_free@Base 2.14 + bd_lvm_vgdata_get_type@Base 2.14 + bd_lvm_vgdeactivate@Base 2.14 + bd_lvm_vgdeactivate_stub@Base 2.14 + bd_lvm_vgextend@Base 2.14 + bd_lvm_vgextend_stub@Base 2.14 + bd_lvm_vginfo@Base 2.14 + bd_lvm_vginfo_stub@Base 2.14 + bd_lvm_vgreduce@Base 2.14 + bd_lvm_vgreduce_stub@Base 2.14 + bd_lvm_vgremove@Base 2.14 + bd_lvm_vgremove_stub@Base 2.14 + bd_lvm_vgrename@Base 2.14 + bd_lvm_vgrename_stub@Base 2.14 + bd_lvm_vgs@Base 2.14 + bd_lvm_vgs_stub@Base 2.14 + bd_md_activate@Base 2.14 + bd_md_activate_stub@Base 2.14 + bd_md_add@Base 2.14 + bd_md_add_stub@Base 2.14 + bd_md_canonicalize_uuid@Base 2.14 + bd_md_canonicalize_uuid_stub@Base 2.14 + bd_md_create@Base 2.14 + bd_md_create_stub@Base 2.14 + bd_md_deactivate@Base 2.14 + bd_md_deactivate_stub@Base 2.14 + bd_md_denominate@Base 2.14 + bd_md_denominate_stub@Base 2.14 + bd_md_destroy@Base 2.14 + bd_md_destroy_stub@Base 2.14 + bd_md_detail@Base 2.14 + bd_md_detail_data_copy@Base 2.14 + bd_md_detail_data_free@Base 2.14 + bd_md_detail_data_get_type@Base 2.14 + bd_md_detail_stub@Base 2.14 + bd_md_error_quark@Base 2.14 + bd_md_examine@Base 2.14 + bd_md_examine_data_copy@Base 2.14 + bd_md_examine_data_free@Base 2.14 + bd_md_examine_data_get_type@Base 2.14 + bd_md_examine_stub@Base 2.14 + bd_md_get_bitmap_location@Base 2.14 + bd_md_get_bitmap_location_stub@Base 2.14 + bd_md_get_md_uuid@Base 2.14 + bd_md_get_md_uuid_stub@Base 2.14 + bd_md_get_status@Base 2.14 + bd_md_get_status_stub@Base 2.14 + bd_md_get_superblock_size@Base 2.14 + bd_md_get_superblock_size_stub@Base 2.14 + bd_md_is_tech_avail@Base 2.14 + bd_md_is_tech_avail_stub@Base 2.14 + bd_md_name_from_node@Base 2.14 + bd_md_name_from_node_stub@Base 2.14 + bd_md_node_from_name@Base 2.14 + bd_md_node_from_name_stub@Base 2.14 + bd_md_nominate@Base 2.14 + bd_md_nominate_stub@Base 2.14 + bd_md_remove@Base 2.14 + bd_md_remove_stub@Base 2.14 + bd_md_request_sync_action@Base 2.14 + bd_md_request_sync_action_stub@Base 2.14 + bd_md_run@Base 2.14 + bd_md_run_stub@Base 2.14 + bd_md_set_bitmap_location@Base 2.14 + bd_md_set_bitmap_location_stub@Base 2.14 + bd_mpath_error_quark@Base 2.14 + bd_mpath_flush_mpaths@Base 2.14 + bd_mpath_flush_mpaths_stub@Base 2.14 + bd_mpath_get_mpath_members@Base 2.14 + bd_mpath_get_mpath_members_stub@Base 2.14 + bd_mpath_is_mpath_member@Base 2.14 + bd_mpath_is_mpath_member_stub@Base 2.14 + bd_mpath_is_tech_avail@Base 2.14 + bd_mpath_is_tech_avail_stub@Base 2.14 + bd_mpath_set_friendly_names@Base 2.14 + bd_mpath_set_friendly_names_stub@Base 2.14 + bd_part_create_part@Base 2.14 + bd_part_create_part_stub@Base 2.14 + bd_part_create_table@Base 2.14 + bd_part_create_table_stub@Base 2.14 + bd_part_delete_part@Base 2.14 + bd_part_delete_part_stub@Base 2.14 + bd_part_disk_spec_copy@Base 2.14 + bd_part_disk_spec_free@Base 2.14 + bd_part_disk_spec_get_type@Base 2.14 + bd_part_error_quark@Base 2.14 + bd_part_get_best_free_region@Base 2.14 + bd_part_get_best_free_region_stub@Base 2.14 + bd_part_get_disk_free_regions@Base 2.14 + bd_part_get_disk_free_regions_stub@Base 2.14 + bd_part_get_disk_parts@Base 2.14 + bd_part_get_disk_parts_stub@Base 2.14 + bd_part_get_disk_spec@Base 2.14 + bd_part_get_disk_spec_stub@Base 2.14 + bd_part_get_flag_str@Base 2.14 + bd_part_get_flag_str_stub@Base 2.14 + bd_part_get_part_by_pos@Base 2.14 + bd_part_get_part_by_pos_stub@Base 2.14 + bd_part_get_part_id@Base 2.14 + bd_part_get_part_id_stub@Base 2.14 + bd_part_get_part_spec@Base 2.14 + bd_part_get_part_spec_stub@Base 2.14 + bd_part_get_part_table_type_str@Base 2.14 + bd_part_get_part_table_type_str_stub@Base 2.14 + bd_part_get_type_str@Base 2.14 + bd_part_get_type_str_stub@Base 2.14 + bd_part_is_tech_avail@Base 2.14 + bd_part_is_tech_avail_stub@Base 2.14 + bd_part_resize_part@Base 2.14 + bd_part_resize_part_stub@Base 2.14 + bd_part_set_disk_flag@Base 2.14 + bd_part_set_disk_flag_stub@Base 2.14 + bd_part_set_part_flag@Base 2.14 + bd_part_set_part_flag_stub@Base 2.14 + bd_part_set_part_flags@Base 2.14 + bd_part_set_part_flags_stub@Base 2.14 + bd_part_set_part_id@Base 2.14 + bd_part_set_part_id_stub@Base 2.14 + bd_part_set_part_name@Base 2.14 + bd_part_set_part_name_stub@Base 2.14 + bd_part_set_part_type@Base 2.14 + bd_part_set_part_type_stub@Base 2.14 + bd_part_spec_copy@Base 2.14 + bd_part_spec_free@Base 2.14 + bd_part_spec_get_type@Base 2.14 + bd_plugin_spec_copy@Base 2.14 + bd_plugin_spec_free@Base 2.14 + bd_plugin_spec_get_type@Base 2.14 + bd_reinit@Base 2.14 + (arch=s390x)bd_s390_dasd_format@Base 2.14 + (arch=s390x)bd_s390_dasd_format_stub@Base 2.14 + (arch=s390x)bd_s390_dasd_is_fba@Base 2.14 + (arch=s390x)bd_s390_dasd_is_fba_stub@Base 2.14 + (arch=s390x)bd_s390_dasd_is_ldl@Base 2.14 + (arch=s390x)bd_s390_dasd_is_ldl_stub@Base 2.14 + (arch=s390x)bd_s390_dasd_needs_format@Base 2.14 + (arch=s390x)bd_s390_dasd_needs_format_stub@Base 2.14 + (arch=s390x)bd_s390_dasd_online@Base 2.14 + (arch=s390x)bd_s390_dasd_online_stub@Base 2.14 + (arch=s390x)bd_s390_error_quark@Base 2.14 + (arch=s390x)bd_s390_is_tech_avail@Base 2.14 + (arch=s390x)bd_s390_is_tech_avail_stub@Base 2.14 + (arch=s390x)bd_s390_sanitize_dev_input@Base 2.14 + (arch=s390x)bd_s390_sanitize_dev_input_stub@Base 2.14 + (arch=s390x)bd_s390_zfcp_offline@Base 2.14 + (arch=s390x)bd_s390_zfcp_offline_stub@Base 2.14 + (arch=s390x)bd_s390_zfcp_online@Base 2.14 + (arch=s390x)bd_s390_zfcp_online_stub@Base 2.14 + (arch=s390x)bd_s390_zfcp_sanitize_lun_input@Base 2.14 + (arch=s390x)bd_s390_zfcp_sanitize_lun_input_stub@Base 2.14 + (arch=s390x)bd_s390_zfcp_sanitize_wwpn_input@Base 2.14 + (arch=s390x)bd_s390_zfcp_sanitize_wwpn_input_stub@Base 2.14 + (arch=s390x)bd_s390_zfcp_scsi_offline@Base 2.14 + (arch=s390x)bd_s390_zfcp_scsi_offline_stub@Base 2.14 + bd_swap_error_quark@Base 2.14 + bd_swap_is_tech_avail@Base 2.14 + bd_swap_is_tech_avail_stub@Base 2.14 + bd_swap_mkswap@Base 2.14 + bd_swap_mkswap_stub@Base 2.14 + bd_swap_set_label@Base 2.14 + bd_swap_set_label_stub@Base 2.14 + bd_swap_swapoff@Base 2.14 + bd_swap_swapoff_stub@Base 2.14 + bd_swap_swapon@Base 2.14 + bd_swap_swapon_stub@Base 2.14 + bd_swap_swapstatus@Base 2.14 + bd_swap_swapstatus_stub@Base 2.14 + bd_switch_init_checks@Base 2.14 + bd_try_init@Base 2.14 + bd_try_reinit@Base 2.14 + get_btrfs_functions@Base 2.14 + get_btrfs_num_functions@Base 2.14 + get_crypto_functions@Base 2.14 + get_crypto_num_functions@Base 2.14 + get_dm_functions@Base 2.14 + get_dm_num_functions@Base 2.14 + get_fs_functions@Base 2.14 + get_fs_num_functions@Base 2.14 + get_kbd_functions@Base 2.14 + get_kbd_num_functions@Base 2.14 + get_loop_functions@Base 2.14 + get_loop_num_functions@Base 2.14 + get_lvm_functions@Base 2.14 + get_lvm_num_functions@Base 2.14 + get_mdraid_functions@Base 2.14 + get_mdraid_num_functions@Base 2.14 + get_mpath_functions@Base 2.14 + get_mpath_num_functions@Base 2.14 + get_part_functions@Base 2.14 + get_part_num_functions@Base 2.14 + (arch=s390x)get_s390_functions@Base 2.14 + (arch=s390x)get_s390_num_functions@Base 2.14 + get_swap_functions@Base 2.14 + get_swap_num_functions@Base 2.14 + load_btrfs_from_plugin@Base 2.14 + load_crypto_from_plugin@Base 2.14 + load_dm_from_plugin@Base 2.14 + load_fs_from_plugin@Base 2.14 + load_kbd_from_plugin@Base 2.14 + load_loop_from_plugin@Base 2.14 + load_lvm_from_plugin@Base 2.14 + load_mdraid_from_plugin@Base 2.14 + load_mpath_from_plugin@Base 2.14 + load_part_from_plugin@Base 2.14 + (arch=s390x)load_s390_from_plugin@Base 2.14 + load_swap_from_plugin@Base 2.14 + unload_btrfs@Base 2.14 + unload_crypto@Base 2.14 + unload_dm@Base 2.14 + unload_fs@Base 2.14 + unload_kbd@Base 2.14 + unload_loop@Base 2.14 + unload_lvm@Base 2.14 + unload_mdraid@Base 2.14 + unload_mpath@Base 2.14 + unload_part@Base 2.14 + (arch=s390x)unload_s390@Base 2.14 + unload_swap@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-btrfs2.symbols libblockdev-2.16/debian/libblockdev-btrfs2.symbols --- libblockdev-2.14/debian/libblockdev-btrfs2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-btrfs2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,29 @@ +libbd_btrfs.so.2 libblockdev-btrfs2 #MINVER# +* Build-Depends-Package: libblockdev-btrfs-dev + bd_btrfs_add_device@Base 2.14 + bd_btrfs_change_label@Base 2.14 + bd_btrfs_check@Base 2.14 + bd_btrfs_check_deps@Base 2.14 + bd_btrfs_close@Base 2.14 + bd_btrfs_create_snapshot@Base 2.14 + bd_btrfs_create_subvolume@Base 2.14 + bd_btrfs_create_volume@Base 2.14 + bd_btrfs_delete_subvolume@Base 2.14 + bd_btrfs_device_info_copy@Base 2.14 + bd_btrfs_device_info_free@Base 2.14 + bd_btrfs_error_quark@Base 2.14 + bd_btrfs_filesystem_info@Base 2.14 + bd_btrfs_filesystem_info_copy@Base 2.14 + bd_btrfs_filesystem_info_free@Base 2.14 + bd_btrfs_get_default_subvolume_id@Base 2.14 + bd_btrfs_init@Base 2.14 + bd_btrfs_is_tech_avail@Base 2.14 + bd_btrfs_list_devices@Base 2.14 + bd_btrfs_list_subvolumes@Base 2.14 + bd_btrfs_mkfs@Base 2.14 + bd_btrfs_remove_device@Base 2.14 + bd_btrfs_repair@Base 2.14 + bd_btrfs_resize@Base 2.14 + bd_btrfs_set_default_subvolume@Base 2.14 + bd_btrfs_subvolume_info_copy@Base 2.14 + bd_btrfs_subvolume_info_free@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-crypto2.symbols libblockdev-2.16/debian/libblockdev-crypto2.symbols --- libblockdev-2.14/debian/libblockdev-crypto2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-crypto2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,26 @@ +libbd_crypto.so.2 libblockdev-crypto2 #MINVER# +* Build-Depends-Package: libblockdev-crypto-dev + bd_crypto_check_deps@Base 2.14 + bd_crypto_close@Base 2.14 + bd_crypto_device_is_luks@Base 2.14 + bd_crypto_error_quark@Base 2.14 + bd_crypto_escrow_device@Base 2.14 + bd_crypto_generate_backup_passphrase@Base 2.14 + bd_crypto_init@Base 2.14 + bd_crypto_is_tech_avail@Base 2.14 + bd_crypto_luks_add_key@Base 2.14 + bd_crypto_luks_add_key_blob@Base 2.14 + bd_crypto_luks_change_key@Base 2.14 + bd_crypto_luks_change_key_blob@Base 2.14 + bd_crypto_luks_close@Base 2.14 + bd_crypto_luks_format@Base 2.14 + bd_crypto_luks_format_blob@Base 2.14 + bd_crypto_luks_open@Base 2.14 + bd_crypto_luks_open_blob@Base 2.14 + bd_crypto_luks_remove_key@Base 2.14 + bd_crypto_luks_remove_key_blob@Base 2.14 + bd_crypto_luks_resize@Base 2.14 + bd_crypto_luks_status@Base 2.14 + bd_crypto_luks_uuid@Base 2.14 + bd_crypto_tc_close@Base 2.14 + bd_crypto_tc_open@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-dm2.symbols libblockdev-2.16/debian/libblockdev-dm2.symbols --- libblockdev-2.14/debian/libblockdev-dm2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-dm2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,17 @@ +libbd_dm.so.2 libblockdev-dm2 #MINVER# +* Build-Depends-Package: libblockdev-dm-dev + bd_dm_activate_raid_set@Base 2.14 + bd_dm_check_deps@Base 2.14 + bd_dm_close@Base 2.14 + bd_dm_create_linear@Base 2.14 + bd_dm_deactivate_raid_set@Base 2.14 + bd_dm_error_quark@Base 2.14 + bd_dm_get_member_raid_sets@Base 2.14 + bd_dm_get_raid_set_type@Base 2.14 + bd_dm_get_subsystem_from_name@Base 2.14 + bd_dm_init@Base 2.14 + bd_dm_is_tech_avail@Base 2.14 + bd_dm_map_exists@Base 2.14 + bd_dm_name_from_node@Base 2.14 + bd_dm_node_from_name@Base 2.14 + bd_dm_remove@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-fs2.symbols libblockdev-2.16/debian/libblockdev-fs2.symbols --- libblockdev-2.14/debian/libblockdev-fs2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-fs2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,80 @@ +libbd_fs.so.2 libblockdev-fs2 #MINVER# +* Build-Depends-Package: libblockdev-fs-dev + bd_fs_can_check@Base 2.14 + bd_fs_can_repair@Base 2.14 + bd_fs_can_resize@Base 2.14 + bd_fs_can_set_label@Base 2.14 + bd_fs_check@Base 2.14 + bd_fs_check_deps@Base 2.14 + bd_fs_clean@Base 2.14 + bd_fs_close@Base 2.14 + bd_fs_error_quark@Base 2.14 + bd_fs_ext2_check@Base 2.14 + bd_fs_ext2_get_info@Base 2.14 + bd_fs_ext2_info_copy@Base 2.14 + bd_fs_ext2_info_free@Base 2.14 + bd_fs_ext2_mkfs@Base 2.14 + bd_fs_ext2_repair@Base 2.14 + bd_fs_ext2_resize@Base 2.14 + bd_fs_ext2_set_label@Base 2.14 + bd_fs_ext2_wipe@Base 2.14 + bd_fs_ext3_check@Base 2.14 + bd_fs_ext3_get_info@Base 2.14 + bd_fs_ext3_info_copy@Base 2.14 + bd_fs_ext3_info_free@Base 2.14 + bd_fs_ext3_mkfs@Base 2.14 + bd_fs_ext3_repair@Base 2.14 + bd_fs_ext3_resize@Base 2.14 + bd_fs_ext3_set_label@Base 2.14 + bd_fs_ext3_wipe@Base 2.14 + bd_fs_ext4_check@Base 2.14 + bd_fs_ext4_get_info@Base 2.14 + bd_fs_ext4_info_copy@Base 2.14 + bd_fs_ext4_info_free@Base 2.14 + bd_fs_ext4_mkfs@Base 2.14 + bd_fs_ext4_repair@Base 2.14 + bd_fs_ext4_resize@Base 2.14 + bd_fs_ext4_set_label@Base 2.14 + bd_fs_ext4_wipe@Base 2.14 + bd_fs_ext_is_tech_avail@Base 2.16 + bd_fs_get_fstype@Base 2.14 + bd_fs_get_mountpoint@Base 2.14 + bd_fs_init@Base 2.14 + bd_fs_is_tech_avail@Base 2.14 + bd_fs_mount@Base 2.14 + bd_fs_ntfs_check@Base 2.14 + bd_fs_ntfs_get_info@Base 2.14 + bd_fs_ntfs_info_copy@Base 2.14 + bd_fs_ntfs_info_free@Base 2.14 + bd_fs_ntfs_is_tech_avail@Base 2.16 + bd_fs_ntfs_mkfs@Base 2.14 + bd_fs_ntfs_repair@Base 2.14 + bd_fs_ntfs_resize@Base 2.14 + bd_fs_ntfs_set_label@Base 2.14 + bd_fs_ntfs_wipe@Base 2.14 + bd_fs_repair@Base 2.14 + bd_fs_resize@Base 2.14 + bd_fs_set_label@Base 2.14 + bd_fs_unmount@Base 2.14 + bd_fs_vfat_check@Base 2.14 + bd_fs_vfat_get_info@Base 2.14 + bd_fs_vfat_info_copy@Base 2.14 + bd_fs_vfat_info_free@Base 2.14 + bd_fs_vfat_is_tech_avail@Base 2.16 + bd_fs_vfat_mkfs@Base 2.14 + bd_fs_vfat_repair@Base 2.14 + bd_fs_vfat_resize@Base 2.14 + bd_fs_vfat_set_label@Base 2.14 + bd_fs_vfat_wipe@Base 2.14 + bd_fs_wipe@Base 2.14 + bd_fs_xfs_check@Base 2.14 + bd_fs_xfs_get_info@Base 2.14 + bd_fs_xfs_info_copy@Base 2.14 + bd_fs_xfs_info_free@Base 2.14 + bd_fs_xfs_is_tech_avail@Base 2.16 + bd_fs_xfs_mkfs@Base 2.14 + bd_fs_xfs_repair@Base 2.14 + bd_fs_xfs_resize@Base 2.14 + bd_fs_xfs_set_label@Base 2.14 + bd_fs_xfs_wipe@Base 2.14 + fs_info@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-fs-dev.install libblockdev-2.16/debian/libblockdev-fs-dev.install --- libblockdev-2.14/debian/libblockdev-fs-dev.install 2017-12-13 14:29:43.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-fs-dev.install 2018-02-20 12:44:30.000000000 +0000 @@ -1,2 +1,3 @@ usr/lib/*/libbd_fs.so +usr/include/blockdev/fs usr/include/blockdev/fs.h diff -Nru libblockdev-2.14/debian/libblockdev-kbd2.symbols libblockdev-2.16/debian/libblockdev-kbd2.symbols --- libblockdev-2.14/debian/libblockdev-kbd2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-kbd2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,28 @@ +libbd_kbd.so.2 libblockdev-kbd2 #MINVER# +* Build-Depends-Package: libblockdev-kbd-dev + bd_kbd_bcache_attach@Base 2.14 + bd_kbd_bcache_create@Base 2.14 + bd_kbd_bcache_destroy@Base 2.14 + bd_kbd_bcache_detach@Base 2.14 + bd_kbd_bcache_get_backing_device@Base 2.14 + bd_kbd_bcache_get_cache_device@Base 2.14 + bd_kbd_bcache_get_mode@Base 2.14 + bd_kbd_bcache_get_mode_from_str@Base 2.14 + bd_kbd_bcache_get_mode_str@Base 2.14 + bd_kbd_bcache_set_mode@Base 2.14 + bd_kbd_bcache_stats_copy@Base 2.14 + bd_kbd_bcache_stats_free@Base 2.14 + bd_kbd_bcache_status@Base 2.14 + bd_kbd_check_deps@Base 2.14 + bd_kbd_close@Base 2.14 + bd_kbd_error_quark@Base 2.14 + bd_kbd_init@Base 2.14 + bd_kbd_is_tech_avail@Base 2.14 + bd_kbd_zram_add_device@Base 2.14 + bd_kbd_zram_create_devices@Base 2.14 + bd_kbd_zram_destroy_devices@Base 2.14 + bd_kbd_zram_get_stats@Base 2.14 + bd_kbd_zram_remove_device@Base 2.14 + bd_kbd_zram_stats_copy@Base 2.14 + bd_kbd_zram_stats_free@Base 2.14 + wait_for_file@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-loop2.symbols libblockdev-2.16/debian/libblockdev-loop2.symbols --- libblockdev-2.14/debian/libblockdev-loop2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-loop2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,14 @@ +libbd_loop.so.2 libblockdev-loop2 #MINVER# +* Build-Depends-Package: libblockdev-loop-dev + bd_loop_check_deps@Base 2.14 + bd_loop_close@Base 2.14 + bd_loop_error_quark@Base 2.14 + bd_loop_get_autoclear@Base 2.14 + bd_loop_get_backing_file@Base 2.14 + bd_loop_get_loop_name@Base 2.14 + bd_loop_init@Base 2.14 + bd_loop_is_tech_avail@Base 2.14 + bd_loop_set_autoclear@Base 2.14 + bd_loop_setup@Base 2.14 + bd_loop_setup_from_fd@Base 2.14 + bd_loop_teardown@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-lvm2.symbols libblockdev-2.16/debian/libblockdev-lvm2.symbols --- libblockdev-2.14/debian/libblockdev-lvm2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-lvm2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,71 @@ +libbd_lvm.so.2 libblockdev-lvm2 #MINVER# +* Build-Depends-Package: libblockdev-lvm-dev + bd_lvm_cache_attach@Base 2.14 + bd_lvm_cache_create_cached_lv@Base 2.14 + bd_lvm_cache_create_pool@Base 2.14 + bd_lvm_cache_detach@Base 2.14 + bd_lvm_cache_get_default_md_size@Base 2.14 + bd_lvm_cache_get_mode_from_str@Base 2.14 + bd_lvm_cache_get_mode_str@Base 2.14 + bd_lvm_cache_pool_convert@Base 2.14 + bd_lvm_cache_pool_name@Base 2.14 + bd_lvm_cache_stats@Base 2.14 + bd_lvm_cache_stats_copy@Base 2.14 + bd_lvm_cache_stats_free@Base 2.14 + bd_lvm_check_deps@Base 2.14 + bd_lvm_close@Base 2.14 + bd_lvm_data_lv_name@Base 2.14 + bd_lvm_error_quark@Base 2.14 + bd_lvm_get_global_config@Base 2.14 + bd_lvm_get_lv_physical_size@Base 2.14 + bd_lvm_get_max_lv_size@Base 2.14 + bd_lvm_get_supported_pe_sizes@Base 2.14 + bd_lvm_get_thpool_meta_size@Base 2.14 + bd_lvm_get_thpool_padding@Base 2.14 + bd_lvm_init@Base 2.14 + bd_lvm_is_supported_pe_size@Base 2.14 + bd_lvm_is_tech_avail@Base 2.14 + bd_lvm_is_valid_thpool_chunk_size@Base 2.14 + bd_lvm_is_valid_thpool_md_size@Base 2.14 + bd_lvm_lvactivate@Base 2.14 + bd_lvm_lvcreate@Base 2.14 + bd_lvm_lvdata_copy@Base 2.14 + bd_lvm_lvdata_free@Base 2.14 + bd_lvm_lvdeactivate@Base 2.14 + bd_lvm_lvinfo@Base 2.14 + bd_lvm_lvorigin@Base 2.14 + bd_lvm_lvremove@Base 2.14 + bd_lvm_lvrename@Base 2.14 + bd_lvm_lvresize@Base 2.14 + bd_lvm_lvs@Base 2.14 + bd_lvm_lvsnapshotcreate@Base 2.14 + bd_lvm_lvsnapshotmerge@Base 2.14 + bd_lvm_metadata_lv_name@Base 2.14 + bd_lvm_pvcreate@Base 2.14 + bd_lvm_pvdata_copy@Base 2.14 + bd_lvm_pvdata_free@Base 2.14 + bd_lvm_pvinfo@Base 2.14 + bd_lvm_pvmove@Base 2.14 + bd_lvm_pvremove@Base 2.14 + bd_lvm_pvresize@Base 2.14 + bd_lvm_pvs@Base 2.14 + bd_lvm_pvscan@Base 2.14 + bd_lvm_round_size_to_pe@Base 2.14 + bd_lvm_set_global_config@Base 2.14 + bd_lvm_thlvcreate@Base 2.14 + bd_lvm_thlvpoolname@Base 2.14 + bd_lvm_thpool_convert@Base 2.14 + bd_lvm_thpoolcreate@Base 2.14 + bd_lvm_thsnapshotcreate@Base 2.14 + bd_lvm_vgactivate@Base 2.14 + bd_lvm_vgcreate@Base 2.14 + bd_lvm_vgdata_copy@Base 2.14 + bd_lvm_vgdata_free@Base 2.14 + bd_lvm_vgdeactivate@Base 2.14 + bd_lvm_vgextend@Base 2.14 + bd_lvm_vginfo@Base 2.14 + bd_lvm_vgreduce@Base 2.14 + bd_lvm_vgremove@Base 2.14 + bd_lvm_vgrename@Base 2.14 + bd_lvm_vgs@Base 2.14 + global_config_lock@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-lvm-dbus2.symbols libblockdev-2.16/debian/libblockdev-lvm-dbus2.symbols --- libblockdev-2.14/debian/libblockdev-lvm-dbus2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-lvm-dbus2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,71 @@ +libbd_lvm-dbus.so.2 libblockdev-lvm-dbus2 #MINVER# +* Build-Depends-Package: libblockdev-lvm-dbus-dev + bd_lvm_cache_attach@Base 2.14 + bd_lvm_cache_create_cached_lv@Base 2.14 + bd_lvm_cache_create_pool@Base 2.14 + bd_lvm_cache_detach@Base 2.14 + bd_lvm_cache_get_default_md_size@Base 2.14 + bd_lvm_cache_get_mode_from_str@Base 2.14 + bd_lvm_cache_get_mode_str@Base 2.14 + bd_lvm_cache_pool_convert@Base 2.14 + bd_lvm_cache_pool_name@Base 2.14 + bd_lvm_cache_stats@Base 2.14 + bd_lvm_cache_stats_copy@Base 2.14 + bd_lvm_cache_stats_free@Base 2.14 + bd_lvm_check_deps@Base 2.14 + bd_lvm_close@Base 2.14 + bd_lvm_data_lv_name@Base 2.14 + bd_lvm_error_quark@Base 2.14 + bd_lvm_get_global_config@Base 2.14 + bd_lvm_get_lv_physical_size@Base 2.14 + bd_lvm_get_max_lv_size@Base 2.14 + bd_lvm_get_supported_pe_sizes@Base 2.14 + bd_lvm_get_thpool_meta_size@Base 2.14 + bd_lvm_get_thpool_padding@Base 2.14 + bd_lvm_init@Base 2.14 + bd_lvm_is_supported_pe_size@Base 2.14 + bd_lvm_is_tech_avail@Base 2.14 + bd_lvm_is_valid_thpool_chunk_size@Base 2.14 + bd_lvm_is_valid_thpool_md_size@Base 2.14 + bd_lvm_lvactivate@Base 2.14 + bd_lvm_lvcreate@Base 2.14 + bd_lvm_lvdata_copy@Base 2.14 + bd_lvm_lvdata_free@Base 2.14 + bd_lvm_lvdeactivate@Base 2.14 + bd_lvm_lvinfo@Base 2.14 + bd_lvm_lvorigin@Base 2.14 + bd_lvm_lvremove@Base 2.14 + bd_lvm_lvrename@Base 2.14 + bd_lvm_lvresize@Base 2.14 + bd_lvm_lvs@Base 2.14 + bd_lvm_lvsnapshotcreate@Base 2.14 + bd_lvm_lvsnapshotmerge@Base 2.14 + bd_lvm_metadata_lv_name@Base 2.14 + bd_lvm_pvcreate@Base 2.14 + bd_lvm_pvdata_copy@Base 2.14 + bd_lvm_pvdata_free@Base 2.14 + bd_lvm_pvinfo@Base 2.14 + bd_lvm_pvmove@Base 2.14 + bd_lvm_pvremove@Base 2.14 + bd_lvm_pvresize@Base 2.14 + bd_lvm_pvs@Base 2.14 + bd_lvm_pvscan@Base 2.14 + bd_lvm_round_size_to_pe@Base 2.14 + bd_lvm_set_global_config@Base 2.14 + bd_lvm_thlvcreate@Base 2.14 + bd_lvm_thlvpoolname@Base 2.14 + bd_lvm_thpool_convert@Base 2.14 + bd_lvm_thpoolcreate@Base 2.14 + bd_lvm_thsnapshotcreate@Base 2.14 + bd_lvm_vgactivate@Base 2.14 + bd_lvm_vgcreate@Base 2.14 + bd_lvm_vgdata_copy@Base 2.14 + bd_lvm_vgdata_free@Base 2.14 + bd_lvm_vgdeactivate@Base 2.14 + bd_lvm_vgextend@Base 2.14 + bd_lvm_vginfo@Base 2.14 + bd_lvm_vgreduce@Base 2.14 + bd_lvm_vgremove@Base 2.14 + bd_lvm_vgrename@Base 2.14 + bd_lvm_vgs@Base 2.14 + global_config_lock@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-mdraid2.symbols libblockdev-2.16/debian/libblockdev-mdraid2.symbols --- libblockdev-2.14/debian/libblockdev-mdraid2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-mdraid2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,31 @@ +libbd_mdraid.so.2 libblockdev-mdraid2 #MINVER# +* Build-Depends-Package: libblockdev-mdraid-dev + bd_md_activate@Base 2.14 + bd_md_add@Base 2.14 + bd_md_canonicalize_uuid@Base 2.14 + bd_md_check_deps@Base 2.14 + bd_md_close@Base 2.14 + bd_md_create@Base 2.14 + bd_md_deactivate@Base 2.14 + bd_md_denominate@Base 2.14 + bd_md_destroy@Base 2.14 + bd_md_detail@Base 2.14 + bd_md_detail_data_copy@Base 2.14 + bd_md_detail_data_free@Base 2.14 + bd_md_error_quark@Base 2.14 + bd_md_examine@Base 2.14 + bd_md_examine_data_copy@Base 2.14 + bd_md_examine_data_free@Base 2.14 + bd_md_get_bitmap_location@Base 2.14 + bd_md_get_md_uuid@Base 2.14 + bd_md_get_status@Base 2.14 + bd_md_get_superblock_size@Base 2.14 + bd_md_init@Base 2.14 + bd_md_is_tech_avail@Base 2.14 + bd_md_name_from_node@Base 2.14 + bd_md_node_from_name@Base 2.14 + bd_md_nominate@Base 2.14 + bd_md_remove@Base 2.14 + bd_md_request_sync_action@Base 2.14 + bd_md_run@Base 2.14 + bd_md_set_bitmap_location@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-part2.symbols libblockdev-2.16/debian/libblockdev-part2.symbols --- libblockdev-2.14/debian/libblockdev-part2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-part2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,31 @@ +libbd_part.so.2 libblockdev-part2 #MINVER# +* Build-Depends-Package: libblockdev-part-dev + bd_part_check_deps@Base 2.14 + bd_part_close@Base 2.14 + bd_part_create_part@Base 2.14 + bd_part_create_table@Base 2.14 + bd_part_delete_part@Base 2.14 + bd_part_disk_spec_copy@Base 2.14 + bd_part_disk_spec_free@Base 2.14 + bd_part_error_quark@Base 2.14 + bd_part_get_best_free_region@Base 2.14 + bd_part_get_disk_free_regions@Base 2.14 + bd_part_get_disk_parts@Base 2.14 + bd_part_get_disk_spec@Base 2.14 + bd_part_get_flag_str@Base 2.14 + bd_part_get_part_by_pos@Base 2.14 + bd_part_get_part_id@Base 2.14 + bd_part_get_part_spec@Base 2.14 + bd_part_get_part_table_type_str@Base 2.14 + bd_part_get_type_str@Base 2.14 + bd_part_init@Base 2.14 + bd_part_is_tech_avail@Base 2.14 + bd_part_resize_part@Base 2.14 + bd_part_set_disk_flag@Base 2.14 + bd_part_set_part_flag@Base 2.14 + bd_part_set_part_flags@Base 2.14 + bd_part_set_part_id@Base 2.14 + bd_part_set_part_name@Base 2.14 + bd_part_set_part_type@Base 2.14 + bd_part_spec_copy@Base 2.14 + bd_part_spec_free@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-part-err2.symbols libblockdev-2.16/debian/libblockdev-part-err2.symbols --- libblockdev-2.14/debian/libblockdev-part-err2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-part-err2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,4 @@ +libbd_part_err.so.2 libblockdev-part-err2 #MINVER# +* Build-Depends-Package: libblockdev-part-err-dev + bd_exc_handler@Base 2.14 + bd_get_error_msg@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-swap2.symbols libblockdev-2.16/debian/libblockdev-swap2.symbols --- libblockdev-2.14/debian/libblockdev-swap2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-swap2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,12 @@ +libbd_swap.so.2 libblockdev-swap2 #MINVER# +* Build-Depends-Package: libblockdev-swap-dev + bd_swap_check_deps@Base 2.14 + bd_swap_close@Base 2.14 + bd_swap_error_quark@Base 2.14 + bd_swap_init@Base 2.14 + bd_swap_is_tech_avail@Base 2.14 + bd_swap_mkswap@Base 2.14 + bd_swap_set_label@Base 2.14 + bd_swap_swapoff@Base 2.14 + bd_swap_swapon@Base 2.14 + bd_swap_swapstatus@Base 2.14 diff -Nru libblockdev-2.14/debian/libblockdev-utils2.symbols libblockdev-2.16/debian/libblockdev-utils2.symbols --- libblockdev-2.14/debian/libblockdev-utils2.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-utils2.symbols 2018-02-20 12:44:30.000000000 +0000 @@ -0,0 +1,31 @@ +libbd_utils.so.2 libblockdev-utils2 #MINVER# +* Build-Depends-Package: libblockdev-utils-dev + bd_extra_arg_copy@Base 2.14 + bd_extra_arg_free@Base 2.14 + bd_extra_arg_get_type@Base 2.14 + bd_extra_arg_new@Base 2.14 + bd_utils_check_util_version@Base 2.14 + bd_utils_dev_utils_error_quark@Base 2.14 + bd_utils_echo_str_to_file@Base 2.14 + bd_utils_exec_and_capture_output@Base 2.14 + bd_utils_exec_and_report_error@Base 2.14 + bd_utils_exec_and_report_error_no_progress@Base 2.14 + bd_utils_exec_and_report_progress@Base 2.14 + bd_utils_exec_and_report_status_error@Base 2.14 + bd_utils_exec_error_quark@Base 2.14 + bd_utils_get_device_symlinks@Base 2.14 + bd_utils_have_kernel_module@Base 2.16 + bd_utils_init_logging@Base 2.14 + bd_utils_init_prog_reporting@Base 2.14 + bd_utils_load_kernel_module@Base 2.16 + bd_utils_module_error_quark@Base 2.16 + bd_utils_prog_reporting_initialized@Base 2.16 + bd_utils_report_finished@Base 2.14 + bd_utils_report_progress@Base 2.14 + bd_utils_report_started@Base 2.14 + bd_utils_resolve_device@Base 2.14 + bd_utils_unload_kernel_module@Base 2.16 + bd_utils_version_cmp@Base 2.14 + get_next_task_id@Base 2.14 + log_task_status@Base 2.14 + diff -Nru libblockdev-2.14/debian/libblockdev-utils-dev.install libblockdev-2.16/debian/libblockdev-utils-dev.install --- libblockdev-2.14/debian/libblockdev-utils-dev.install 2017-12-13 14:29:43.000000000 +0000 +++ libblockdev-2.16/debian/libblockdev-utils-dev.install 2018-02-20 12:44:30.000000000 +0000 @@ -1,5 +1,6 @@ usr/lib/*/libbd_utils.so usr/lib/*/pkgconfig/blockdev-utils.pc +usr/include/blockdev/module.h usr/include/blockdev/utils.h usr/include/blockdev/sizes.h usr/include/blockdev/exec.h diff -Nru libblockdev-2.14/debian/rules libblockdev-2.16/debian/rules --- libblockdev-2.14/debian/rules 2017-12-13 14:29:43.000000000 +0000 +++ libblockdev-2.16/debian/rules 2018-02-20 12:44:30.000000000 +0000 @@ -1,30 +1,13 @@ #!/usr/bin/make -f -# See debhelper(7) (uncomment to enable) -# output every command that modifies files on the build system. -#export DH_VERBOSE = 1 - -# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* -DPKG_EXPORT_BUILDFLAGS = 1 -include /usr/share/dpkg/default.mk -# see FEATURE AREAS in dpkg-buildflags(1) export DEB_BUILD_MAINT_OPTIONS = hardening=+all +export DEB_LDFLAGS_MAINT_APPEND = -Wl,-z,defs -Wl,--as-needed -# see ENVIRONMENT in dpkg-buildflags(1) -# package maintainers to append CFLAGS -#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic -# package maintainers to append LDFLAGS -#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed - - -# main packaging script based on dh7 syntax %: dh $@ --with python3,gir override_dh_auto_configure: - dh_auto_configure -- \ - --disable-tests \ - --without-s390 + dh_auto_configure -- --disable-tests --without-s390 override_dh_install: find debian/tmp -name '*.la' | xargs rm -f @@ -33,3 +16,6 @@ override_dh_missing: dh_missing --fail-missing + +override_dh_makeshlibs: + dh_makeshlibs -- -c4 diff -Nru libblockdev-2.14/dist/libblockdev.spec.in libblockdev-2.16/dist/libblockdev.spec.in --- libblockdev-2.14/dist/libblockdev.spec.in 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/dist/libblockdev.spec.in 2018-02-08 11:10:41.000000000 +0000 @@ -66,7 +66,7 @@ %define configure_opts %{?distro_copts} %{?btrfs_copts} %{?crypto_copts} %{?dm_copts} %{?loop_copts} %{?lvm_copts} %{?lvm_dbus_copts} %{?mdraid_copts} %{?mpath_copts} %{?swap_copts} %{?kbd_copts} %{?part_copts} %{?fs_copts} %{?gi_copts} Name: libblockdev -Version: 2.14 +Version: 2.16 Release: 1%{?dist} Summary: A library for low-level manipulation with block devices License: LGPLv2+ @@ -135,6 +135,7 @@ %endif %package utils +BuildRequires: kmod-devel Summary: A library with utility functions for the libblockdev library %description utils @@ -254,7 +255,6 @@ %if %{with_kbd} %package kbd -BuildRequires: kmod-devel BuildRequires: libbytesize-devel Summary: The KBD plugin for the libblockdev library Requires: %{name}-utils%{?_isa} >= 0.11 @@ -649,6 +649,7 @@ %{_includedir}/blockdev/exec.h %{_includedir}/blockdev/extra_arg.h %{_includedir}/blockdev/dev_utils.h +%{_includedir}/blockdev/module.h %if %{with_btrfs} @@ -691,7 +692,9 @@ %files fs-devel %{_libdir}/libbd_fs.so %dir %{_includedir}/blockdev +%dir %{_includedir}/blockdev/fs %{_includedir}/blockdev/fs.h +%{_includedir}/blockdev/fs/*.h %endif @@ -797,6 +800,42 @@ %files plugins-all %changelog +* Thu Feb 08 2018 Vojtech Trefny - 2.16-1 +- Add tests for progress report (jtulak) +- Add e2fsck progress (jtulak) +- Add progress reporting infrastructure for Ext fsck (jtulak) +- Add a function to test if prog. reporting was initialized (jtulak) +- Add support for LUKS 2 opening and key management (vtrefny) +- Fix few more links for project and documentation website (vtrefny) +- Sync the spec file with downstream (vpodzime) +- Check if 'journalctl' is available before trying to use it in tests (vtrefny) +- Update 'Testing libblockdev' section in documentation (vtrefny) +- Fix link to online documentation (vtrefny) +- Fix how the new kernel module functions are added to docs (vpodzime) + +* Fri Dec 01 2017 Vratislav Podzimek - 2.15-1 +- Do not use the 'btrfs' plugin in overrides tests (vpodzime) +- Do not use the btrfs plugin in library tests (vpodzime) +- Check for btrfs module availability in btrfs module (vtrefny) +- Move kernel modules (un)loading and checking into utils (vtrefny) +- Free locale struct in kbd plugin (vtrefny) +- Add test for setting partition flags on GPT (vtrefny) +- Use only sgdisk to set flags on GPT (vtrefny) +- Move the fs.h file to its original place (vpodzime) +- Add a HACKING.rst file (vpodzime) +- Mark bcache tests as unstable (vpodzime) +- Fix memory leaks in bd_fs_vfat_get_info() (vpodzime) +- Revert the behaviour of bd_fs_check_deps() (vpodzime) +- Split the bd_fs_is_tech_avail() implementation (vpodzime) +- Split the FS plugin source into multiple files (vpodzime) +- Fix bd_s390_dasd_format (vponcova) +- Mark unstable tests as such (vpodzime) +- bd_s390_dasd_is_ldl should be true only for LDL DADSs (vponcova) +- Do not lie about tag creation (vpodzime) + +* Wed Nov 08 2017 Zbigniew Jędrzejewski-Szmek - 2.14-2 +- Rebuild for cryptsetup-2.0.0 + * Tue Oct 31 2017 Vratislav Podzimek - 2.14-1 - Support the legacy boot GPT flag (intrigeri) - Respect the version in the blockdev.pc file (vpodzime) diff -Nru libblockdev-2.14/docs/libblockdev-docs.xml.in libblockdev-2.16/docs/libblockdev-docs.xml.in --- libblockdev-2.14/docs/libblockdev-docs.xml.in 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/docs/libblockdev-docs.xml.in 2018-02-08 11:10:41.000000000 +0000 @@ -11,10 +11,10 @@ for libblockdev @VERSION@. The latest version of this documentation can be found on-line at http://rhinstaller.github.io/libblockdev/. + url="http://storaged.org/libblockdev/">http://storaged.org/libblockdev/. The latest version of the code can be found at https://github.com/rhinstaller/libblockdev + url="https://github.com/storaged-project/libblockdev">https://github.com/storaged-project/libblockdev @@ -108,7 +108,37 @@ make test-all executes all tests, including ones which may result in kernel panic or - take more time to complete. + take more time to complete or + + make test-plugin-NAME + + executes only tests for given plugin and similarly + + make fast-test-plugin-NAME + + executes only fast tests for given plugin. + + + + It is also possible to run only subset of available tests or only one test + using the `run_tests.py` script: + + # python3 tests/run_tests.py fs_test.GenericResize + + executes all tests from the GenericResize test class + from filesystem plugin test cases and + + # python3 tests/run_tests.py fs_test.GenericResize.test_ext2_generic_resize + + executes only test_ext2_generic_resize from this class. + + This script also allows skipping slow tests or running potentially dangerous + tests. Use: + + $ python3 tests/run_tests.py --help + + to see all available options. + @@ -123,15 +153,6 @@ is equivalent to `make test-all'. - - - libblockdev also supports running the test and coverage targets using Python3. - To do this define the PYTHON or COVERAGE variables respectively. For example: - - make PYTHON=python3 test - - make COVERAGE=coverage3 coverage - diff -Nru libblockdev-2.14/docs/libblockdev-sections.txt libblockdev-2.16/docs/libblockdev-sections.txt --- libblockdev-2.14/docs/libblockdev-sections.txt 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/docs/libblockdev-sections.txt 2018-02-08 11:10:41.000000000 +0000 @@ -148,6 +148,9 @@ bd_extra_arg_get_type bd_utils_resolve_device bd_utils_get_device_symlinks +bd_utils_have_kernel_module +bd_utils_load_kernel_module +bd_utils_unload_kernel_module EXBIBYTE EiB GIBIBYTE diff -Nru libblockdev-2.14/.gitignore libblockdev-2.16/.gitignore --- libblockdev-2.14/.gitignore 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/.gitignore 2018-02-08 11:10:41.000000000 +0000 @@ -6,8 +6,7 @@ **/*.pyc *libblockdev*.tar.gz src/lib/plugin_apis/*.[ch] -src/lib/plugin_apis/btrfs.api -src/plugins/btrfs.h +src/plugins/.dirstamp BlockDev-*.gir BlockDev-*.typelib Makefile @@ -41,6 +40,7 @@ **/*.stamp **/*.bak include/blockdev/*.h +include/blockdev/fs docs/libblockdev-decl-list.txt docs/libblockdev-decl.txt docs/libblockdev-overrides.txt diff -Nru libblockdev-2.14/HACKING.md libblockdev-2.16/HACKING.md --- libblockdev-2.14/HACKING.md 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/HACKING.md 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,36 @@ +CODING STYLE +============ + + - Please follow the coding style already used. + + - Spaces, not tabs, are used (except for Makefiles). + + +MAKING RELEASES +=============== + + - [ ] ``sudo git clean -xdf`` + + - [ ] ``./autogen.sh && ./configure`` + + - [ ] ``make bumpver`` + + - [ ] Add a new entry to the *NEWS.rst* file (full list of changes should be + generated with ``make shortlog``). + + - [ ] Commit all the changes as *New version - $VERSION*. + + - [ ] ``make release`` (requires a GPG key to sign the tag) + + - [ ] ``git push && git push --tags`` + + - [ ] Edit the new release (for the new tag) at GitHub and: + + - [ ] add some detailed information about it (from the *NEWS.rst*) file to it, + + - [ ] upload the tarball created above (``make release``) to the release. + + - [ ] Update the documentation by rsyncing the contents of the *docs/html* + folder elsewhere, switching to the *gh-pages* branch, rsyncing the + contents back and commiting it as an update of the docs for the new + release. diff -Nru libblockdev-2.14/include/blockdev/Makefile.am libblockdev-2.16/include/blockdev/Makefile.am --- libblockdev-2.14/include/blockdev/Makefile.am 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/include/blockdev/Makefile.am 2018-02-08 11:10:41.000000000 +0000 @@ -2,8 +2,11 @@ for header in ${srcdir}/../../src/plugins/*.h; do ln -sf $${header} ./; done for header in ${srcdir}/../../src/utils/*.h; do ln -sf $${header} ./; done for header in ${srcdir}/../../src/lib/*.h; do ln -sf $${header} ./; done + mkdir -p fs; + cd fs; for header in ${srcdir}/../../../src/plugins/fs/*.h; do ln -sf $${header} ./; done clean-local: rm -f *.h + rm -rf fs MAINTAINERCLEANFILES = Makefile.in diff -Nru libblockdev-2.14/Makefile.am libblockdev-2.16/Makefile.am --- libblockdev-2.14/Makefile.am 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/Makefile.am 2018-02-08 11:10:41.000000000 +0000 @@ -15,7 +15,7 @@ configure depcomp install-sh ltmain.sh missing py-compile compile ar-lib \ m4/*.m4 -LIBDIRS = src/utils/.libs:src/plugins/.libs:src/lib/.libs +LIBDIRS = src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs GIDIR = src/lib if WITH_PYTHON3 @@ -101,7 +101,7 @@ tag: TAG="$(PACKAGE_VERSION)-1" ; \ - git tag -a -s -m "Tag as $$TAG" -f "$$TAG" ; \ + git tag -a -s -m "Tag as $$TAG" -f "$$TAG" && \ echo "Tagged as $$TAG" rpmlog: diff -Nru libblockdev-2.14/NEWS.rst libblockdev-2.16/NEWS.rst --- libblockdev-2.14/NEWS.rst 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/NEWS.rst 2018-02-08 11:10:41.000000000 +0000 @@ -1,3 +1,97 @@ +Libblockdev 2.16 +---------------- + +New minor release of the libblockdev library with multiple fixes. See below +for details. + +**Notable changes** + +- features + + - LUKS 2 support for luks_open/close and luks_add/remove/change_key + + - Progress report support for ext filesystem checks + + +**Full list of changes** + +Jan Tulak (4): +- Add a function to test if prog. reporting was initialized +- Add progress reporting infrastructure for Ext fsck +- Add e2fsck progress +- Add tests for progress report + +Vojtech Trefny (5): +- Fix link to online documentation +- Update 'Testing libblockdev' section in documentation +- Check if 'journalctl' is available before trying to use it in tests +- Fix few more links for project and documentation website +- Add support for LUKS 2 opening and key management + +Vratislav Podzimek (2): +- Fix how the new kernel module functions are added to docs +- Sync the spec file with downstream + + +Libblockdev 2.15 +---------------- + +New minor release of the libblockdev library with multiple fixes and quite big +refactorization changes (in the file system plugin). See below for details. + + +**Notable changes** + +- fixes + + - Fix bd_s390_dasd_format() and bd_s390_dasd_is_ldl(). + + - Fix how GPT patition flags are set. + + - Check the *btrfs* module availability as part of checking the *btrfs* + plugin's dependencies. + + - Fix memory leaks in bd_fs_vfat_get_info() + + - Fix the file system plugin's dependency checking mechanisms. + + +- features + + - Mark some of the tests as unstable so that their failures are reported, but + ignored in the overall test suite status. + + - The file system plugin is now split into multiple source files making it + easier to add support for more file systems and technologies. + + +**Full list of changes** + +Vendula Poncova (2): +- bd_s390_dasd_is_ldl should be true only for LDL DADSs +- Fix bd_s390_dasd_format + +Vojtech Trefny (5): +- Use only sgdisk to set flags on GPT +- Add test for setting partition flags on GPT +- Free locale struct in kbd plugin +- Move kernel modules (un)loading and checking into utils +- Check for btrfs module availability in btrfs module + +Vratislav Podzimek (11): +- Do not lie about tag creation +- Mark unstable tests as such +- Split the FS plugin source into multiple files +- Split the bd_fs_is_tech_avail() implementation +- Revert the behaviour of bd_fs_check_deps() +- Fix memory leaks in bd_fs_vfat_get_info() +- Mark bcache tests as unstable +- Add a HACKING.rst file +- Move the fs.h file to its original place +- Do not use the btrfs plugin in library tests +- Do not use the 'btrfs' plugin in overrides tests + + Libblockdev 2.14 ---------------- diff -Nru libblockdev-2.14/src/lib/blockdev.pc.in libblockdev-2.16/src/lib/blockdev.pc.in --- libblockdev-2.14/src/lib/blockdev.pc.in 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/lib/blockdev.pc.in 2018-02-08 11:10:41.000000000 +0000 @@ -5,7 +5,7 @@ Name: BlockDev Description: Library for doing low-level operations with block devices -URL: https://github.com/rhinstaller/libblockdev +URL: https://github.com/storaged-project/libblockdev Version: @VERSION@ Requires: glib-2.0 Libs: -lblockdev diff -Nru libblockdev-2.14/src/lib/plugin_apis/part.api libblockdev-2.16/src/lib/plugin_apis/part.api --- libblockdev-2.14/src/lib/plugin_apis/part.api 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/lib/plugin_apis/part.api 2018-02-08 11:10:41.000000000 +0000 @@ -27,6 +27,20 @@ BD_PART_DISK_FLAG_GPT_PMBR_BOOT = 1 } BDPartDiskFlag; +/* BpG-skip */ +/** + * BDPartFlag: + * + * Partition flags supported by libblockdev. First part of the flags (up to + * @BD_PART_FLAG_BASIC_LAST) corresponds to the flags supported by libparted + * (see https://www.gnu.org/software/parted/manual/parted.html#set). Second + * part corresponds to the flags supported by sgdisk (GPT, see `sgdisk -A=list`). + * + * The only exception from the above is @BD_PART_FLAG_LEGACY_BOOT which is + * supported by libparted too but is GPT specific. + * + */ +/* BpG-skip-end */ typedef enum { BD_PART_FLAG_BOOT = 1 << 1, BD_PART_FLAG_ROOT = 1 << 2, @@ -380,6 +394,8 @@ * not * * Note: Unsets all the other flags on the partition. + * Only GPT-specific flags and the legacy boot flag are supported on GPT + * partition tables. * * Tech category: %BD_PART_TECH_MODE_MODIFY_PART + the tech according to the partition table type */ diff -Nru libblockdev-2.14/src/plugins/btrfs.c libblockdev-2.16/src/plugins/btrfs.c --- libblockdev-2.14/src/plugins/btrfs.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/btrfs.c 2018-02-08 11:10:41.000000000 +0000 @@ -92,6 +92,7 @@ } static volatile guint avail_deps = 0; +static volatile guint avail_module_deps = 0; static GMutex deps_check_lock; #define DEPS_BTRFS 0 @@ -102,6 +103,12 @@ {"btrfs", BTRFS_MIN_VERSION, NULL, "[Bb]trfs.* v([\\d\\.]+)"}, }; +#define MODULE_DEPS_BTRFS 0 +#define MODULE_DEPS_BTRFS_MASK (1 << MODULE_DEPS_BTRFS) +#define MODULE_DEPS_LAST 1 + +static gchar* module_deps[MODULE_DEPS_LAST] = { "btrfs" }; + /** * bd_btrfs_check_deps: @@ -128,6 +135,15 @@ ret = ret && status; } + for (i=0; i < MODULE_DEPS_LAST; i++) { + status = check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, &error); + if (!status) { + g_warning ("%s", error->message); + g_clear_error (&error); + } + ret = ret && status; + } + if (!ret) g_warning("Cannot load the BTRFS plugin"); @@ -171,7 +187,8 @@ */ gboolean bd_btrfs_is_tech_avail (BDBtrfsTech tech UNUSED, guint64 mode UNUSED, GError **error UNUSED) { /* all tech-mode combinations are supported by this implementation of the plugin */ - return check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error); + return check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) && + check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); } static BDBtrfsDeviceInfo* get_device_info_from_match (GMatchInfo *match_info) { @@ -284,7 +301,8 @@ guint8 next_arg = 1; gboolean success = FALSE; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; if (!devices || (g_strv_length ((gchar **) devices) < 1)) { @@ -351,7 +369,8 @@ */ gboolean bd_btrfs_add_device (const gchar *mountpoint, const gchar *device, const BDExtraArg **extra, GError **error) { const gchar *argv[6] = {"btrfs", "device", "add", device, mountpoint, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; return bd_utils_exec_and_report_error (argv, extra, error); @@ -371,7 +390,8 @@ */ gboolean bd_btrfs_remove_device (const gchar *mountpoint, const gchar *device, const BDExtraArg **extra, GError **error) { const gchar *argv[6] = {"btrfs", "device", "delete", device, mountpoint, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; return bd_utils_exec_and_report_error (argv, extra, error); @@ -394,7 +414,8 @@ gboolean success = FALSE; const gchar *argv[5] = {"btrfs", "subvol", "create", NULL, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; if (g_str_has_suffix (mountpoint, "/")) @@ -426,7 +447,8 @@ gboolean success = FALSE; const gchar *argv[5] = {"btrfs", "subvol", "delete", NULL, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; if (g_str_has_suffix (mountpoint, "/")) @@ -460,7 +482,8 @@ guint64 ret = 0; const gchar *argv[5] = {"btrfs", "subvol", "get-default", mountpoint, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; regex = g_regex_new ("ID (\\d+) .*", 0, 0, error); @@ -513,7 +536,8 @@ const gchar *argv[6] = {"btrfs", "subvol", "set-default", NULL, mountpoint, NULL}; gboolean ret = FALSE; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; argv[3] = g_strdup_printf ("%"G_GUINT64_FORMAT, subvol_id); @@ -540,7 +564,8 @@ const gchar *argv[7] = {"btrfs", "subvol", "snapshot", NULL, NULL, NULL, NULL}; guint next_arg = 3; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; if (ro) { @@ -580,7 +605,8 @@ GPtrArray *dev_infos = g_ptr_array_new (); BDBtrfsDeviceInfo** ret = NULL; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; regex = g_regex_new (pattern, G_REGEX_EXTENDED, 0, error); @@ -661,7 +687,8 @@ BDBtrfsSubvolumeInfo* swap_item = NULL; BDBtrfsSubvolumeInfo** ret = NULL; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; if (snapshots_only) { @@ -771,7 +798,8 @@ GMatchInfo *match_info = NULL; BDBtrfsFilesystemInfo *ret = NULL; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; regex = g_regex_new (pattern, G_REGEX_EXTENDED, 0, error); @@ -838,7 +866,8 @@ const gchar *argv[6] = {"btrfs", "filesystem", "resize", NULL, mountpoint, NULL}; gboolean ret = FALSE; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; argv[3] = g_strdup_printf ("%"G_GUINT64_FORMAT, size); @@ -862,7 +891,8 @@ gboolean bd_btrfs_check (const gchar *device, const BDExtraArg **extra, GError **error) { const gchar *argv[4] = {"btrfs", "check", device, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; return bd_utils_exec_and_report_error (argv, extra, error); @@ -882,7 +912,8 @@ gboolean bd_btrfs_repair (const gchar *device, const BDExtraArg **extra, GError **error) { const gchar *argv[5] = {"btrfs", "check", "--repair", device, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; return bd_utils_exec_and_report_error (argv, extra, error); @@ -902,7 +933,8 @@ gboolean bd_btrfs_change_label (const gchar *mountpoint, const gchar *label, GError **error) { const gchar *argv[6] = {"btrfs", "filesystem", "label", mountpoint, label, NULL}; - if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) || + !check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error)) return FALSE; return bd_utils_exec_and_report_error (argv, NULL, error); diff -Nru libblockdev-2.14/src/plugins/check_deps.c libblockdev-2.16/src/plugins/check_deps.c --- libblockdev-2.14/src/plugins/check_deps.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/check_deps.c 2018-02-08 11:10:41.000000000 +0000 @@ -66,3 +66,57 @@ val = (guint) g_atomic_int_get (avail_deps); return (val & req_deps) != 0; } + +gboolean __attribute__ ((visibility ("hidden"))) +check_module_deps (volatile guint *avail_deps, guint req_deps, gchar **modules, guint l_modules, GMutex *deps_check_lock, GError **error) { + guint i = 0; + gboolean ret = FALSE; + GError *l_error = NULL; + guint val = 0; + + val = (guint) g_atomic_int_get (avail_deps); + if (val & req_deps) + /* we have everything we need */ + return TRUE; + + /* else */ + /* grab a lock to prevent multiple checks from running in parallel */ + g_mutex_lock (deps_check_lock); + + /* maybe the other thread found out we have all we needed? */ + val = (guint) g_atomic_int_get (avail_deps); + if (val & req_deps) { + g_mutex_unlock (deps_check_lock); + return TRUE; + } + + for (i=0; i < l_modules; i++) { + if (((1 << i) & req_deps) && !((1 << i) & val)) { + ret = bd_utils_have_kernel_module (modules[i], &l_error); + /* if not ret and l_error -> set/prepend error */ + if (!ret) { + if (l_error) { + if (*error) + g_prefix_error (error, "%s\n", l_error->message); + else + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_MODULE_CHECK_ERROR, + "%s", l_error->message); + g_clear_error (&l_error); + } else { + /* no error from have_kernel_module means we don't have it */ + if (*error) + g_prefix_error (error, "Kernel module '%s' not available\n", modules[i]); + else + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_MODULE_CHECK_ERROR, + "Kernel module '%s' not available", modules[i]); + } + + } else + g_atomic_int_or (avail_deps, 1 << i); + } + } + + g_mutex_unlock (deps_check_lock); + val = (guint) g_atomic_int_get (avail_deps); + return (val & req_deps) != 0; +} diff -Nru libblockdev-2.14/src/plugins/check_deps.h libblockdev-2.16/src/plugins/check_deps.h --- libblockdev-2.14/src/plugins/check_deps.h 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/check_deps.h 2018-02-08 11:10:41.000000000 +0000 @@ -27,3 +27,4 @@ } UtilDep; gboolean check_deps (volatile guint *avail_deps, guint req_deps, UtilDep *deps_specs, guint l_deps, GMutex *deps_check_lock, GError **error); +gboolean check_module_deps (volatile guint *avail_deps, guint req_deps, gchar **modules, guint l_modules, GMutex *deps_check_lock, GError **error); diff -Nru libblockdev-2.14/src/plugins/crypto.c libblockdev-2.16/src/plugins/crypto.c --- libblockdev-2.14/src/plugins/crypto.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/crypto.c 2018-02-08 11:10:41.000000000 +0000 @@ -31,6 +31,10 @@ #include "crypto.h" +#ifndef CRYPT_LUKS +#define CRYPT_LUKS NULL +#endif + /** * SECTION: crypto * @short_description: plugin for operations with encrypted devices @@ -191,7 +195,7 @@ return FALSE; } - ret = crypt_load (cd, CRYPT_LUKS1, NULL); + ret = crypt_load (cd, CRYPT_LUKS, NULL); crypt_free (cd); return (ret == 0); } @@ -218,7 +222,7 @@ return NULL; } - ret_num = crypt_load (cd, CRYPT_LUKS1, NULL); + ret_num = crypt_load (cd, CRYPT_LUKS, NULL); if (ret_num != 0) { g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, "Failed to load device: %s", strerror_l(-ret_num, c_locale)); @@ -476,7 +480,7 @@ return FALSE; } - ret = crypt_load (cd, CRYPT_LUKS1, NULL); + ret = crypt_load (cd, CRYPT_LUKS, NULL); if (ret != 0) { g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, "Failed to load device's parameters: %s", strerror_l(-ret, c_locale)); @@ -621,7 +625,7 @@ return FALSE; } - ret = crypt_load (cd, CRYPT_LUKS1, NULL); + ret = crypt_load (cd, CRYPT_LUKS, NULL); if (ret != 0) { g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, "Failed to load device's parameters: %s", strerror_l(-ret, c_locale)); @@ -740,7 +744,7 @@ return FALSE; } - ret = crypt_load (cd, CRYPT_LUKS1, NULL); + ret = crypt_load (cd, CRYPT_LUKS, NULL); if (ret != 0) { g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, "Failed to load device's parameters: %s", strerror_l(-ret, c_locale)); @@ -844,7 +848,7 @@ return FALSE; } - ret = crypt_load (cd, CRYPT_LUKS1, NULL); + ret = crypt_load (cd, CRYPT_LUKS, NULL); if (ret != 0) { g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, "Failed to load device's parameters: %s", strerror_l(-ret, c_locale)); diff -Nru libblockdev-2.14/src/plugins/fs/common.c libblockdev-2.16/src/plugins/fs/common.c --- libblockdev-2.14/src/plugins/fs/common.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/common.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "fs.h" +#include "common.h" + +gint __attribute__ ((visibility ("hidden"))) +synced_close (gint fd) { + gint ret = 0; + ret = fsync (fd); + if (close (fd) != 0) + ret = 1; + return ret; +} + +gboolean __attribute__ ((visibility ("hidden"))) +has_fs (blkid_probe probe, const gchar *device, const gchar *fs_type, GError **error) { + gint status = 0; + const gchar *value = NULL; + size_t len = 0; + + status = blkid_do_safeprobe (probe); + if (status != 0) { + if (status < 0) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to probe the device '%s'", device); + return FALSE; + } + + if (fs_type) { + status = blkid_probe_lookup_value (probe, "TYPE", &value, &len); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get filesystem type for the device '%s'", device); + return FALSE; + } + + if (strncmp (value, fs_type, len-1) != 0) { + return FALSE; + } + } + + blkid_reset_probe (probe); + return TRUE; +} + +gboolean __attribute__ ((visibility ("hidden"))) +wipe_fs (const gchar *device, const gchar *fs_type, gboolean wipe_all, GError **error) { + blkid_probe probe = NULL; + gint fd = 0; + gint status = 0; + const gchar *value = NULL; + size_t len = 0; + guint64 progress_id = 0; + gchar *msg = NULL; + gboolean has_fs_type = TRUE; + guint n_try = 0; + + msg = g_strdup_printf ("Started wiping '%s' signatures from the device '%s'", fs_type, device); + progress_id = bd_utils_report_started (msg); + g_free (msg); + + probe = blkid_new_probe (); + if (!probe) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + fd = open (device, O_RDWR|O_CLOEXEC); + if (fd == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + blkid_free_probe (probe); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { + status = blkid_probe_set_device (probe, fd, 0, 0); + if (status != 0) + g_usleep (100 * 1000); /* microseconds */ + } + status = blkid_probe_set_device (probe, fd, 0, 0); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + blkid_probe_enable_partitions(probe, 1); + blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC); + blkid_probe_enable_superblocks(probe, 1); + blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_USAGE | BLKID_SUBLKS_TYPE | + BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); + + for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { + status = blkid_do_probe (probe); + if (status != 0) + g_usleep (100 * 1000); /* microseconds */ + } + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to probe the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + status = blkid_probe_lookup_value (probe, "USAGE", &value, NULL); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get signature type for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + if (strncmp (value, "filesystem", 10) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_INVAL, + "The signature on the device '%s' is of type '%s', not 'filesystem'", device, value); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + if (fs_type) { + status = blkid_probe_lookup_value (probe, "TYPE", &value, &len); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get filesystem type for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + if (strncmp (value, fs_type, len-1) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_INVAL, + "The file system type on the device '%s' is '%s', not '%s'", device, value, fs_type); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + } + + status = blkid_do_wipe (probe, FALSE); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to wipe the filesystem signature on the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + blkid_reset_probe (probe); + + if (wipe_all) { + has_fs_type = has_fs (probe, device, fs_type, error); + + while (has_fs_type) { + status = blkid_do_probe (probe); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to probe the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + status = blkid_do_wipe (probe, FALSE); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to wipe the filesystem signature on the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + blkid_reset_probe (probe); + has_fs_type = has_fs (probe, device, fs_type, error); + + } + } + + blkid_free_probe (probe); + synced_close (fd); + + bd_utils_report_finished (progress_id, "Completed"); + + return TRUE; +} diff -Nru libblockdev-2.14/src/plugins/fs/common.h libblockdev-2.16/src/plugins/fs/common.h --- libblockdev-2.14/src/plugins/fs/common.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/common.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,11 @@ +#include +#include + +#ifndef BD_FS_COMMON +#define BD_FS_COMMON + +gint synced_close (gint fd); +gboolean has_fs (blkid_probe probe, const gchar *device, const gchar *fs_type, GError **error); +gboolean wipe_fs (const gchar *device, const gchar *fs_type, gboolean wipe_all, GError **error); + +#endif /* BD_FS_COMMON */ diff -Nru libblockdev-2.14/src/plugins/fs/ext.c libblockdev-2.16/src/plugins/fs/ext.c --- libblockdev-2.14/src/plugins/fs/ext.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/ext.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#include +#include + +#include "common.h" +#include "fs.h" +#include "ext.h" + +#define EXT2 "ext2" +#define EXT3 "ext3" +#define EXT4 "ext4" + +static volatile guint avail_deps = 0; +static GMutex deps_check_lock; + +#define DEPS_MKE2FS 0 +#define DEPS_MKE2FS_MASK (1 << DEPS_MKE2FS) +#define DEPS_E2FSCK 1 +#define DEPS_E2FSCK_MASK (1 << DEPS_E2FSCK) +#define DEPS_TUNE2FS 2 +#define DEPS_TUNE2FS_MASK (1 << DEPS_TUNE2FS) +#define DEPS_DUMPE2FS 3 +#define DEPS_DUMPE2FS_MASK (1 << DEPS_DUMPE2FS) +#define DEPS_RESIZE2FS 4 +#define DEPS_RESIZE2FS_MASK (1 << DEPS_RESIZE2FS) + +#define DEPS_LAST 5 + +static UtilDep deps[DEPS_LAST] = { + {"mke2fs", NULL, NULL, NULL}, + {"e2fsck", NULL, NULL, NULL}, + {"tune2fs", NULL, NULL, NULL}, + {"dumpe2fs", NULL, NULL, NULL}, + {"resize2fs", NULL, NULL, NULL}, +}; + +static guint32 fs_mode_util[BD_FS_MODE_LAST+1] = { + /* mkfs wipe check repair set-label query resize */ + DEPS_MKE2FS_MASK, 0, DEPS_E2FSCK_MASK, DEPS_E2FSCK_MASK, DEPS_TUNE2FS_MASK, DEPS_DUMPE2FS_MASK, DEPS_RESIZE2FS_MASK +}; + +#define UNUSED __attribute__((unused)) + +static gint8 compute_percents (guint8 pass_cur, guint8 pass_total, gint val_cur, gint val_total) { + gint perc; + gint one_pass; + /* first get a percentage in the current pass/stage */ + perc = (val_cur * 100) / val_total; + + /* now map it to the total progress, splitting the stages equally */ + one_pass = 100 / pass_total; + perc = ((pass_cur - 1) * one_pass) + (perc / pass_total); + + return perc; +} + +/** + * filter_line_fsck: (skip) + * Filter one line - decide what to do with it. + * + * Returns: Zero or positive number as a percentage, -1 if not a percentage, -2 on an error + */ +static gint8 filter_line_fsck (const gchar * line, guint8 total_stages, GError **error) { + static GRegex *output_regex = NULL; + GMatchInfo *match_info; + gint8 perc = -1; + + if (output_regex == NULL) { + /* Compile regular expression that matches to e2fsck progress output */ + output_regex = g_regex_new ("^([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) (/.*)", 0, 0, error); + if (output_regex == NULL) { + return -2; + } + } + + /* Execute regular expression */ + if (g_regex_match (output_regex, line, 0, &match_info)) { + guint8 stage; + gint64 val_cur; + gint64 val_total; + + /* The output_regex ensures we have a number in these matches, so we can skip + * tests for conversion errors. + */ + stage = (guint8) g_ascii_strtoull (g_match_info_fetch (match_info, 1), (char **)NULL, 10); + val_cur = g_ascii_strtoll (g_match_info_fetch (match_info, 2), (char **)NULL, 10); + val_total = g_ascii_strtoll (g_match_info_fetch (match_info, 3), (char **)NULL, 10); + perc = compute_percents (stage, total_stages, val_cur, val_total); + } else { + g_match_info_free (match_info); + return -1; + } + g_match_info_free (match_info); + return perc; +} + +static gboolean extract_e2fsck_progress (const gchar *line, guint8 *completion) { + /* A magic number 5, e2fsck has 5 stages, but this can't be read from the output in advance. */ + gint8 perc; + GError **error = NULL; + + perc = filter_line_fsck (line, 5, error); + if (perc < 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "An error occured when trying to parse a line with progress"); + return FALSE; + } + + *completion = perc; + return TRUE; +} + + +/** + * bd_fs_ext_is_tech_avail: + * @tech: the queried tech + * @mode: a bit mask of queried modes of operation (#BDFSTechMode) for @tech + * @error: (out): place to store error (details about why the @tech-@mode combination is not available) + * + * Returns: whether the @tech-@mode combination is available -- supported by the + * plugin implementation and having all the runtime dependencies available + */ +gboolean bd_fs_ext_is_tech_avail (BDFSTech tech UNUSED, guint64 mode, GError **error) { + guint32 required = 0; + guint i = 0; + for (i = 0; i <= BD_FS_MODE_LAST; i++) + if (mode & (1 << i)) + required |= fs_mode_util[i]; + + return check_deps (&avail_deps, required, deps, DEPS_LAST, &deps_check_lock, error); +} + +/** + * bd_fs_ext2_info_copy: (skip) + * + * Creates a new copy of @data. + */ +BDFSExt2Info* bd_fs_ext2_info_copy (BDFSExt2Info *data) { + BDFSExt2Info *ret = g_new0 (BDFSExt2Info, 1); + + ret->label = g_strdup (data->label); + ret->uuid = g_strdup (data->uuid); + ret->state = g_strdup (data->state); + ret->block_size = data->block_size; + ret->block_count = data->block_count; + ret->free_blocks = data->free_blocks; + + return ret; +} + +/** + * bd_fs_ext3_info_copy: (skip) + * + * Creates a new copy of @data. + */ +BDFSExt3Info* bd_fs_ext3_info_copy (BDFSExt3Info *data) { + return (BDFSExt3Info*) bd_fs_ext2_info_copy (data); +} + +/** + * bd_fs_ext4_info_copy: (skip) + * + * Creates a new copy of @data. + */ +BDFSExt4Info* bd_fs_ext4_info_copy (BDFSExt4Info *data) { + return (BDFSExt4Info*) bd_fs_ext2_info_copy (data); +} + +/** + * bd_fs_ext2_info_free: (skip) + * + * Frees @data. + */ +void bd_fs_ext2_info_free (BDFSExt2Info *data) { + g_free (data->label); + g_free (data->uuid); + g_free (data->state); + g_free (data); +} + +/** + * bd_fs_ext3_info_free: (skip) + * + * Frees @data. + */ +void bd_fs_ext3_info_free (BDFSExt3Info *data) { + bd_fs_ext2_info_free ((BDFSExt2Info*) data); +} + +/** + * bd_fs_ext4_info_free: (skip) + * + * Frees @data. + */ +void bd_fs_ext4_info_free (BDFSExt4Info *data) { + bd_fs_ext2_info_free ((BDFSExt2Info*) data); +} + +static gboolean ext_mkfs (const gchar *device, const BDExtraArg **extra, const gchar *ext_version, GError **error) { + const gchar *args[6] = {"mke2fs", "-t", ext_version, "-F", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_MKE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, extra, error); +} + +/** + * bd_fs_ext2_mkfs: + * @device: the device to create a new ext2 fs on + * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now + * passed to the 'mke2fs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether a new ext2 fs was successfully created on @device or not + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_MKFS + */ +gboolean bd_fs_ext2_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { + return ext_mkfs (device, extra, EXT2, error); +} + +/** + * bd_fs_ext3_mkfs: + * @device: the device to create a new ext3 fs on + * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now + * passed to the 'mke2fs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether a new ext3 fs was successfully created on @device or not + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_MKFS + */ +gboolean bd_fs_ext3_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { + return ext_mkfs (device, extra, EXT3, error); +} + +/** + * bd_fs_ext4_mkfs: + * @device: the device to create a new ext4 fs on + * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now + * passed to the 'mkfs.ext4' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether a new ext4 fs was successfully created on @device or not + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_MKFS + */ +gboolean bd_fs_ext4_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { + return ext_mkfs (device, extra, EXT4, error); +} + +/** + * bd_fs_ext2_wipe: + * @device: the device to wipe an ext2 signature from + * @error: (out): place to store error (if any) + * + * Returns: whether an ext2 signature was successfully wiped from the @device or + * not + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_ext2_wipe (const gchar *device, GError **error) { + return wipe_fs (device, EXT2, FALSE, error); +} + +/** + * bd_fs_ext3_wipe: + * @device: the device to wipe an ext3 signature from + * @error: (out): place to store error (if any) + * + * Returns: whether an ext3 signature was successfully wiped from the @device or + * not + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_ext3_wipe (const gchar *device, GError **error) { + return wipe_fs (device, EXT3, FALSE, error); +} + +/** + * bd_fs_ext4_wipe: + * @device: the device to wipe an ext4 signature from + * @error: (out): place to store error (if any) + * + * Returns: whether an ext4 signature was successfully wiped from the @device or + * not + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_ext4_wipe (const gchar *device, GError **error) { + return wipe_fs (device, EXT4, FALSE, error); +} + +static gboolean ext_check (const gchar *device, const BDExtraArg **extra, GError **error) { + /* Force checking even if the file system seems clean. AND + * Open the filesystem read-only, and assume an answer of no to all + * questions. */ + const gchar *args_progress[7] = {"e2fsck", "-f", "-n", "-C", "1", device, NULL}; + const gchar *args[5] = {"e2fsck", "-f", "-n", device, NULL}; + gint status = 0; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_E2FSCK_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + if (bd_utils_prog_reporting_initialized ()) { + ret = bd_utils_exec_and_report_progress (args_progress, extra, extract_e2fsck_progress, &status, error); + } else { + ret = bd_utils_exec_and_report_status_error (args, extra, &status, error); + } + + if (!ret && (status == 4)) { + /* no error should be reported for exit code 4 - File system errors left uncorrected */ + g_clear_error (error); + } + return ret; +} + +/** + * bd_fs_ext2_check: + * @device: the device the file system on which to check + * @extra: (allow-none) (array zero-terminated=1): extra options for the check (right now + * passed to the 'e2fsck' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an ext2 file system on the @device is clean or not + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_ext2_check (const gchar *device, const BDExtraArg **extra, GError **error) { + return ext_check (device, extra, error); +} + +/** + * bd_fs_ext3_check: + * @device: the device the file system on which to check + * @extra: (allow-none) (array zero-terminated=1): extra options for the check (right now + * passed to the 'e2fsck' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an ext3 file system on the @device is clean or not + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_ext3_check (const gchar *device, const BDExtraArg **extra, GError **error) { + return ext_check (device, extra, error); +} + +/** + * bd_fs_ext4_check: + * @device: the device the file system on which to check + * @extra: (allow-none) (array zero-terminated=1): extra options for the check (right now + * passed to the 'e2fsck' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an ext4 file system on the @device is clean or not + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_ext4_check (const gchar *device, const BDExtraArg **extra, GError **error) { + return ext_check (device, extra, error); +} + +static gboolean ext_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { + /* Force checking even if the file system seems clean. AND + * Automatically repair what can be safely repaired. OR + * Assume an answer of `yes' to all questions. */ + const gchar *args_progress[7] = {"e2fsck", "-f", "-n", "-C", "1", device, NULL}; + const gchar *args[5] = {"e2fsck", "-f", unsafe ? "-y" : "-p", device, NULL}; + gint status = 0; + + if (!check_deps (&avail_deps, DEPS_E2FSCK_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + if (bd_utils_prog_reporting_initialized ()) { + return bd_utils_exec_and_report_progress (args_progress, extra, extract_e2fsck_progress, &status, error); + } else { + return bd_utils_exec_and_report_status_error (args, extra, &status, error); + } +} + +/** + * bd_fs_ext2_repair: + * @device: the device the file system on which to repair + * @unsafe: whether to do unsafe operations too + * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now + * passed to the 'e2fsck' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an ext2 file system on the @device was successfully repaired + * (if needed) or not (error is set in that case) + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_ext2_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { + return ext_repair (device, unsafe, extra, error); +} + +/** + * bd_fs_ext3_repair: + * @device: the device the file system on which to repair + * @unsafe: whether to do unsafe operations too + * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now + * passed to the 'e2fsck' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an ext3 file system on the @device was successfully repaired + * (if needed) or not (error is set in that case) + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_ext3_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { + return ext_repair (device, unsafe, extra, error); +} + +/** + * bd_fs_ext4_repair: + * @device: the device the file system on which to repair + * @unsafe: whether to do unsafe operations too + * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now + * passed to the 'e2fsck' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an ext4 file system on the @device was successfully repaired + * (if needed) or not (error is set in that case) + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_ext4_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { + return ext_repair (device, unsafe, extra, error); +} + +static gboolean ext_set_label (const gchar *device, const gchar *label, GError **error) { + const gchar *args[5] = {"tune2fs", "-L", label, device, NULL}; + + if (!check_deps (&avail_deps, DEPS_TUNE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, NULL, error); +} + +/** + * bd_fs_ext2_set_label: + * @device: the device the file system on which to set label for + * @label: label to set + * @error: (out): place to store error (if any) + * + * Returns: whether the label of ext2 file system on the @device was + * successfully set or not + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_ext2_set_label (const gchar *device, const gchar *label, GError **error) { + return ext_set_label (device, label, error); +} + +/** + * bd_fs_ext3_set_label: + * @device: the device the file system on which to set label for + * @label: label to set + * @error: (out): place to store error (if any) + * + * Returns: whether the label of ext3 file system on the @device was + * successfully set or not + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_ext3_set_label (const gchar *device, const gchar *label, GError **error) { + return ext_set_label (device, label, error); +} + +/** + * bd_fs_ext4_set_label: + * @device: the device the file system on which to set label for + * @label: label to set + * @error: (out): place to store error (if any) + * + * Returns: whether the label of ext4 file system on the @device was + * successfully set or not + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_ext4_set_label (const gchar *device, const gchar *label, GError **error) { + return ext_set_label (device, label, error); +} + +/** + * parse_output_vars: (skip) + * @str: string to parse + * @item_sep: item separator(s) (key-value pairs separator) + * @key_val_sep: key-value separator(s) (typically ":" or "=") + * @num_items: (out): number of parsed items (key-value pairs) + * + * Returns: (transfer full): GHashTable containing the key-value pairs parsed + * from the @str. + */ +static GHashTable* parse_output_vars (const gchar *str, const gchar *item_sep, const gchar *key_val_sep, guint *num_items) { + GHashTable *table = NULL; + gchar **items = NULL; + gchar **item_p = NULL; + gchar **key_val = NULL; + + table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + *num_items = 0; + + items = g_strsplit_set (str, item_sep, 0); + for (item_p=items; *item_p; item_p++) { + key_val = g_strsplit (*item_p, key_val_sep, 2); + if (g_strv_length (key_val) == 2) { + /* we only want to process valid lines (with the separator) */ + g_hash_table_insert (table, g_strstrip (key_val[0]), g_strstrip (key_val[1])); + (*num_items)++; + } else + /* invalid line, just free key_val */ + g_strfreev (key_val); + } + + g_strfreev (items); + return table; +} + +static BDFSExtInfo* get_ext_info_from_table (GHashTable *table, gboolean free_table) { + BDFSExtInfo *ret = g_new0 (BDFSExtInfo, 1); + gchar *value = NULL; + + ret->label = g_strdup ((gchar*) g_hash_table_lookup (table, "Filesystem volume name")); + if ((!ret->label) || (g_strcmp0 (ret->label, "") == 0)) + ret->label = g_strdup (""); + ret->uuid = g_strdup ((gchar*) g_hash_table_lookup (table, "Filesystem UUID")); + ret->state = g_strdup ((gchar*) g_hash_table_lookup (table, "Filesystem state")); + + value = (gchar*) g_hash_table_lookup (table, "Block size"); + if (value) + ret->block_size = g_ascii_strtoull (value, NULL, 0); + else + ret->block_size = 0; + value = (gchar*) g_hash_table_lookup (table, "Block count"); + if (value) + ret->block_count = g_ascii_strtoull (value, NULL, 0); + else + ret->block_count = 0; + value = (gchar*) g_hash_table_lookup (table, "Free blocks"); + if (value) + ret->free_blocks = g_ascii_strtoull (value, NULL, 0); + else + ret->free_blocks = 0; + + if (free_table) + g_hash_table_destroy (table); + + return ret; +} + +static BDFSExtInfo* ext_get_info (const gchar *device, GError **error) { + const gchar *args[4] = {"dumpe2fs", "-h", device, NULL}; + gboolean success = FALSE; + gchar *output = NULL; + GHashTable *table = NULL; + guint num_items = 0; + BDFSExtInfo *ret = NULL; + + if (!check_deps (&avail_deps, DEPS_DUMPE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + success = bd_utils_exec_and_capture_output (args, NULL, &output, error); + if (!success) { + /* error is already populated */ + return FALSE; + } + + table = parse_output_vars (output, "\n", ":", &num_items); + g_free (output); + if (!table || (num_items == 0)) { + /* something bad happened or some expected items were missing */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse ext4 file system information"); + if (table) + g_hash_table_destroy (table); + return NULL; + } + + ret = get_ext_info_from_table (table, TRUE); + if (!ret) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse ext4 file system information"); + return NULL; + } + + return ret; +} + +/** + * bd_fs_ext2_get_info: + * @device: the device the file system of which to get info for + * @error: (out): place to store error (if any) + * + * Returns: (transfer full): information about the file system on @device or + * %NULL in case of error + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_QUERY + */ +BDFSExt2Info* bd_fs_ext2_get_info (const gchar *device, GError **error) { + return (BDFSExt2Info*) ext_get_info (device, error); +} + +/** + * bd_fs_ext3_get_info: + * @device: the device the file system of which to get info for + * @error: (out): place to store error (if any) + * + * Returns: (transfer full): information about the file system on @device or + * %NULL in case of error + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_QUERY + */ +BDFSExt3Info* bd_fs_ext3_get_info (const gchar *device, GError **error) { + return (BDFSExt3Info*) ext_get_info (device, error); +} + +/** + * bd_fs_ext4_get_info: + * @device: the device the file system of which to get info for + * @error: (out): place to store error (if any) + * + * Returns: (transfer full): information about the file system on @device or + * %NULL in case of error + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_QUERY + */ +BDFSExt4Info* bd_fs_ext4_get_info (const gchar *device, GError **error) { + return (BDFSExt4Info*) ext_get_info (device, error); +} + +static gboolean ext_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { + const gchar *args[4] = {"resize2fs", device, NULL, NULL}; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_RESIZE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + if (new_size != 0) + /* resize2fs doesn't understand bytes, just 512B sectors */ + args[2] = g_strdup_printf ("%"G_GUINT64_FORMAT"s", new_size / 512); + ret = bd_utils_exec_and_report_error (args, extra, error); + + g_free ((gchar *) args[2]); + return ret; +} + +/** + * bd_fs_ext2_resize: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system (if 0, the file system is + * adapted to the underlying block device) + * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now + * passed to the 'resize2fs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether the file system on @device was successfully resized or not + * + * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_ext2_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { + return ext_resize (device, new_size, extra, error); +} + +/** + * bd_fs_ext3_resize: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system (if 0, the file system is + * adapted to the underlying block device) + * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now + * passed to the 'resize2fs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether the file system on @device was successfully resized or not + * + * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_ext3_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { + return ext_resize (device, new_size, extra, error); +} + +/** + * bd_fs_ext4_resize: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system (if 0, the file system is + * adapted to the underlying block device) + * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now + * passed to the 'resize2fs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether the file system on @device was successfully resized or not + * + * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_ext4_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { + return ext_resize (device, new_size, extra, error); +} diff -Nru libblockdev-2.14/src/plugins/fs/ext.h libblockdev-2.16/src/plugins/fs/ext.h --- libblockdev-2.14/src/plugins/fs/ext.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/ext.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,53 @@ +#include +#include + +#ifndef BD_FS_EXT +#define BD_FS_EXT + +typedef struct BDFSExtInfo { + gchar *label; + gchar *uuid; + gchar *state; + guint64 block_size; + guint64 block_count; + guint64 free_blocks; +} BDFSExtInfo; + +typedef struct BDFSExtInfo BDFSExt4Info; +typedef struct BDFSExtInfo BDFSExt3Info; +typedef struct BDFSExtInfo BDFSExt2Info; + +BDFSExt2Info* bd_fs_ext2_info_copy (BDFSExt2Info *data); +void bd_fs_ext2_info_free (BDFSExt2Info *data); + +BDFSExt3Info* bd_fs_ext3_info_copy (BDFSExt3Info *data); +void bd_fs_ext3_info_free (BDFSExt3Info *data); + +BDFSExt4Info* bd_fs_ext4_info_copy (BDFSExt4Info *data); +void bd_fs_ext4_info_free (BDFSExt4Info *data); + +gboolean bd_fs_ext2_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext2_wipe (const gchar *device, GError **error); +gboolean bd_fs_ext2_check (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext2_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext2_set_label (const gchar *device, const gchar *label, GError **error); +BDFSExt2Info* bd_fs_ext2_get_info (const gchar *device, GError **error); +gboolean bd_fs_ext2_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error); + +gboolean bd_fs_ext3_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext3_wipe (const gchar *device, GError **error); +gboolean bd_fs_ext3_check (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext3_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext3_set_label (const gchar *device, const gchar *label, GError **error); +BDFSExt3Info* bd_fs_ext3_get_info (const gchar *device, GError **error); +gboolean bd_fs_ext3_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error); + +gboolean bd_fs_ext4_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext4_wipe (const gchar *device, GError **error); +gboolean bd_fs_ext4_check (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext4_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ext4_set_label (const gchar *device, const gchar *label, GError **error); +BDFSExt4Info* bd_fs_ext4_get_info (const gchar *device, GError **error); +gboolean bd_fs_ext4_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error); + +#endif /* BD_FS_EXT */ diff -Nru libblockdev-2.14/src/plugins/fs/generic.c libblockdev-2.16/src/plugins/fs/generic.c --- libblockdev-2.14/src/plugins/fs/generic.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/generic.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "generic.h" +#include "mount.h" +#include "fs.h" +#include "common.h" +#include "ext.h" +#include "xfs.h" +#include "vfat.h" +#include "ntfs.h" + +typedef enum { + BD_FS_RESIZE, + BD_FS_REPAIR, + BD_FS_CHECK, + BD_FS_LABEL +} BDFsOpType; + +/** + * BDFSInfo: + * @type: filesystem identifier, must be present + * @check_util: required utility for consistency checking, "" if not needed and NULL for no support + * @repair_util: required utility for repair, "" if not needed and NULL for no support + * @resize_util: required utility for resize, "" if not needed and NULL for no support + * @resize_mode: resize availability flags, 0 if no support + */ +typedef struct BDFSInfo +{ + const gchar *type; + const gchar *check_util; + const gchar *repair_util; + const gchar *resize_util; + BDFsResizeFlags resize_mode; + const gchar *label_util; +} BDFSInfo; + +const BDFSInfo fs_info[] = { + {"xfs", "xfs_db", "xfs_repair", "xfs_growfs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW, "xfs_admin"}, + {"ext2", "e2fsck", "e2fsck", "resize2fs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "tune2fs"}, + {"ext3", "e2fsck", "e2fsck", "resize2fs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "tune2fs"}, + {"ext4", "e2fsck", "e2fsck", "resize2fs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "tune2fs"}, + {"vfat", "fsck.vfat", "fsck.vfat", "", BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "fatlabel"}, + {"ntfs", "ntfsfix", "ntfsfix", "ntfsresize", BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "ntfslabel"}, + {NULL, NULL, NULL, NULL, 0, NULL} +}; + +static const BDFSInfo * +get_fs_info (const gchar *type) +{ + g_return_val_if_fail (type != NULL, NULL); + + for (guint n = 0; fs_info[n].type != NULL; n++) { + if (strcmp (fs_info[n].type, type) == 0) + return &fs_info[n]; + } + + return NULL; +} + +/** + * bd_fs_wipe: + * @device: the device to wipe signatures from + * @all: whether to wipe all (%TRUE) signatures or just the first (%FALSE) one + * @error: (out): place to store error (if any) + * + * Returns: whether signatures were successfully wiped on @device or not + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_wipe (const gchar *device, gboolean all, GError **error) { + blkid_probe probe = NULL; + gint fd = 0; + gint status = 0; + guint64 progress_id = 0; + gchar *msg = NULL; + guint n_try = 0; + + msg = g_strdup_printf ("Started wiping signatures from the device '%s'", device); + progress_id = bd_utils_report_started (msg); + g_free (msg); + + probe = blkid_new_probe (); + if (!probe) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a new probe"); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + fd = open (device, O_RDWR|O_CLOEXEC); + if (fd == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to open the device '%s'", device); + blkid_free_probe (probe); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + /* we may need to try mutliple times with some delays in case the device is + busy at the very moment */ + for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { + status = blkid_probe_set_device (probe, fd, 0, 0); + if (status != 0) + g_usleep (100 * 1000); /* microseconds */ + } + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + blkid_probe_enable_partitions(probe, 1); + blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC); + blkid_probe_enable_superblocks(probe, 1); + blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); + + /* we may need to try mutliple times with some delays in case the device is + busy at the very moment */ + for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { + status = blkid_do_safeprobe (probe); + if (status == 1) + break; + if (status < 0) + g_usleep (100 * 1000); /* microseconds */ + } + if (status == 1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOFS, + "No signature detected on the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + blkid_reset_probe (probe); + status = blkid_do_probe (probe); + + if (status < 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to probe the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + status = blkid_do_wipe (probe, FALSE); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to wipe signatures on the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + while (all && (blkid_do_probe (probe) == 0)) { + status = blkid_do_wipe (probe, FALSE); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to wipe signatures on the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + } + + blkid_free_probe (probe); + synced_close (fd); + + bd_utils_report_finished (progress_id, "Completed"); + + return TRUE; +} + +/** + * bd_fs_clean: + * @device: the device to clean + * @error: (out): place to store error (if any) + * + * Clean all signatures from @device. + * Difference between this and bd_fs_wipe() is that this function doesn't + * return error if @device is already empty. This will also always remove + * all signatures from @device, not only the first one. + * + * Returns: whether @device was successfully cleaned or not + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_clean (const gchar *device, GError **error) { + gboolean ret = FALSE; + + ret = bd_fs_wipe (device, TRUE, error); + + if (!ret) { + if (g_error_matches (*error, BD_FS_ERROR, BD_FS_ERROR_NOFS)) { + /* ignore 'empty device' error */ + g_clear_error (error); + return TRUE; + } else { + g_prefix_error (error, "Failed to clean %s:", device); + return FALSE; + } + } else + return TRUE; +} + +/** + * bd_fs_get_fstype: + * @device: the device to probe + * @error: (out): place to store error (if any) + * + * Get first signature on @device as a string. + * + * Returns: (transfer full): type of filesystem found on @device, %NULL in case + * no signature has been detected or in case of error + * (@error is set in this case) + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY + */ +gchar* bd_fs_get_fstype (const gchar *device, GError **error) { + blkid_probe probe = NULL; + gint fd = 0; + gint status = 0; + const gchar *value = NULL; + gchar *fstype = NULL; + size_t len = 0; + guint n_try = 0; + + probe = blkid_new_probe (); + if (!probe) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a new probe"); + return FALSE; + } + + fd = open (device, O_RDWR|O_CLOEXEC); + if (fd == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to open the device '%s'", device); + blkid_free_probe (probe); + return FALSE; + } + + /* we may need to try mutliple times with some delays in case the device is + busy at the very moment */ + for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { + status = blkid_probe_set_device (probe, fd, 0, 0); + if (status != 0) + g_usleep (100 * 1000); /* microseconds */ + } + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + return FALSE; + } + + blkid_probe_enable_partitions (probe, 1); + blkid_probe_set_partitions_flags (probe, BLKID_PARTS_MAGIC); + blkid_probe_enable_superblocks (probe, 1); + blkid_probe_set_superblocks_flags (probe, BLKID_SUBLKS_USAGE | BLKID_SUBLKS_TYPE | + BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); + + /* we may need to try mutliple times with some delays in case the device is + busy at the very moment */ + for (n_try=5, status=-1; !(status == 0 || status == 1) && (n_try > 0); n_try--) { + status = blkid_do_safeprobe (probe); + if (status < 0) + g_usleep (100 * 1000); /* microseconds */ + } + if (status < 0) { + /* -1 or -2 = error during probing*/ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to probe the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } else if (status == 1) { + /* 1 = nothing detected */ + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } + + status = blkid_probe_lookup_value (probe, "USAGE", &value, &len); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get usage for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } + + if (strncmp (value, "filesystem", 10) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_INVAL, + "The signature on the device '%s' is of type '%s', not 'filesystem'", device, value); + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } + + status = blkid_probe_lookup_value (probe, "TYPE", &value, &len); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get filesystem type for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } + + fstype = g_strdup (value); + blkid_free_probe (probe); + synced_close (fd); + + return fstype; +} + +/** + * xfs_resize_device: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system *in bytes* + * (if 0, the file system is adapted to the underlying block device) + * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now + * passed to the 'xfs_growfs' utility) + * @error: (out): place to store error (if any) + * + * This is just a helper function for bd_fs_resize. + * + * Returns: whether the file system on @device was successfully resized or not + */ +static gboolean xfs_resize_device (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { + g_autofree gchar* mountpoint = NULL; + gboolean ret = FALSE; + gboolean success = FALSE; + gboolean unmount = FALSE; + GError *local_error = NULL; + BDFSXfsInfo* xfs_info = NULL; + + mountpoint = bd_fs_get_mountpoint (device, error); + if (!mountpoint) { + if (*error == NULL) { + /* device is not mounted -- we need to mount it */ + mountpoint = g_build_path (G_DIR_SEPARATOR_S, g_get_tmp_dir (), "blockdev.XXXXXX", NULL); + mountpoint = g_mkdtemp (mountpoint); + if (!mountpoint) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create temporary directory for mounting '%s' " + "before resizing it.", device); + return FALSE; + } + ret = bd_fs_mount (device, mountpoint, "xfs", NULL, NULL, error); + if (!ret) { + g_prefix_error (error, "Failed to mount '%s' before resizing it: ", device); + return FALSE; + } else + unmount = TRUE; + } else { + g_prefix_error (error, "Error when trying to get mountpoint for '%s': ", device); + return FALSE; + } + } + + xfs_info = bd_fs_xfs_get_info (device, error); + if (!xfs_info) { + return FALSE; + } + + new_size = (new_size + xfs_info->block_size - 1) / xfs_info->block_size; + bd_fs_xfs_info_free (xfs_info); + + success = bd_fs_xfs_resize (mountpoint, new_size, extra, error); + + if (unmount) { + ret = bd_fs_unmount (mountpoint, FALSE, FALSE, NULL, &local_error); + if (!ret) { + if (success) { + /* resize was successful but unmount failed */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_UNMOUNT_FAIL, + "Failed to unmount '%s' after resizing it: %s", + device, local_error->message); + g_clear_error (&local_error); + return FALSE; + } else + /* both resize and unmount were unsuccessful but the error + from the resize is more important so just ignore the + unmount error */ + g_clear_error (&local_error); + } + } + + return success; +} + + +static gboolean device_operation (const gchar *device, BDFsOpType op, guint64 new_size, const gchar *label, GError **error) { + const gchar* op_name = NULL; + g_autofree gchar* fstype = NULL; + + fstype = bd_fs_get_fstype (device, error); + if (!fstype) { + if (*error == NULL) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOFS, + "No filesystem detected on the device '%s'", device); + return FALSE; + } else { + g_prefix_error (error, "Error when trying to detect filesystem on '%s': ", device); + return FALSE; + } + } + + if (g_strcmp0 (fstype, "ext2") == 0 || g_strcmp0 (fstype, "ext3") == 0 + || g_strcmp0 (fstype, "ext4") == 0) { + switch (op) { + case BD_FS_RESIZE: + return bd_fs_ext4_resize (device, new_size, NULL, error); + case BD_FS_REPAIR: + return bd_fs_ext4_repair (device, TRUE, NULL, error); + case BD_FS_CHECK: + return bd_fs_ext4_check (device, NULL, error); + case BD_FS_LABEL: + return bd_fs_ext4_set_label (device, label, error); + } + } else if (g_strcmp0 (fstype, "xfs") == 0) { + switch (op) { + case BD_FS_RESIZE: + return xfs_resize_device (device, new_size, NULL, error); + case BD_FS_REPAIR: + return bd_fs_xfs_repair (device, NULL, error); + case BD_FS_CHECK: + return bd_fs_xfs_check (device, error); + case BD_FS_LABEL: + return bd_fs_xfs_set_label (device, label, error); + } + } else if (g_strcmp0 (fstype, "vfat") == 0) { + switch (op) { + case BD_FS_RESIZE: + return bd_fs_vfat_resize (device, new_size, error); + case BD_FS_REPAIR: + return bd_fs_vfat_repair (device, NULL, error); + case BD_FS_CHECK: + return bd_fs_vfat_check (device, NULL, error); + case BD_FS_LABEL: + return bd_fs_vfat_set_label (device, label, error); + } + } else if (g_strcmp0 (fstype, "ntfs") == 0) { + switch (op) { + case BD_FS_RESIZE: + return bd_fs_ntfs_resize (device, new_size, error); + case BD_FS_REPAIR: + return bd_fs_ntfs_repair (device, error); + case BD_FS_CHECK: + return bd_fs_ntfs_check (device, error); + case BD_FS_LABEL: + return bd_fs_ntfs_set_label (device, label, error); + } + } + switch (op) { + case BD_FS_RESIZE: + op_name = "Resizing"; + break; + case BD_FS_REPAIR: + op_name = "Repairing"; + break; + case BD_FS_CHECK: + op_name = "Checking"; + break; + case BD_FS_LABEL: + op_name = "Setting the label of"; + break; + } + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_SUPPORTED, + "%s filesystem '%s' is not supported.", op_name, fstype); + return FALSE; +} + +/** + * bd_fs_resize: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system (if 0, the file system is + * adapted to the underlying block device) + * @error: (out): place to store error (if any) + * + * Resize filesystem on @device. This calls other fs resize functions from this + * plugin based on detected filesystem (e.g. bd_fs_xfs_resize for XFS). This + * function will return an error for unknown/unsupported filesystems. + * + * Returns: whether the file system on @device was successfully resized or not + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_resize (const gchar *device, guint64 new_size, GError **error) { + return device_operation (device, BD_FS_RESIZE, new_size, NULL, error); +} + +/** + * bd_fs_repair: + * @device: the device the file system of which to repair + * @error: (out): place to store error (if any) + * + * Repair filesystem on @device. This calls other fs repair functions from this + * plugin based on detected filesystem (e.g. bd_fs_xfs_repair for XFS). This + * function will return an error for unknown/unsupported filesystems. + * + * Returns: whether the file system on @device was successfully repaired or not + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_repair (const gchar *device, GError **error) { + return device_operation (device, BD_FS_REPAIR, 0, NULL, error); + } + +/** + * bd_fs_check: + * @device: the device the file system of which to check + * @error: (out): place to store error (if any) + * + * Check filesystem on @device. This calls other fs check functions from this + * plugin based on detected filesystem (e.g. bd_fs_xfs_check for XFS). This + * function will return an error for unknown/unsupported filesystems. + * + * Returns: whether the file system on @device passed the consistency check or not + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_check (const gchar *device, GError **error) { + return device_operation (device, BD_FS_CHECK, 0, NULL, error); +} + +/** + * bd_fs_set_label: + * @device: the device with file system to set the label for + * @error: (out): place to store error (if any) + * + * Set label for filesystem on @device. This calls other fs label functions from this + * plugin based on detected filesystem (e.g. bd_fs_xfs_set_label for XFS). This + * function will return an error for unknown/unsupported filesystems. + * + * Returns: whether the file system on @device was successfully relabled or not + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_set_label (const gchar *device, const gchar *label, GError **error) { + return device_operation (device, BD_FS_LABEL, 0, label, error); +} + +static gboolean query_fs_operation (const gchar *fs_type, BDFsOpType op, gchar **required_utility, BDFsResizeFlags *mode, GError **error) { + gboolean ret; + const BDFSInfo *fsinfo = NULL; + const gchar* op_name = NULL; + const gchar* exec_util = NULL; + + if (required_utility != NULL) + *required_utility = NULL; + + if (mode != NULL) + *mode = 0; + + fsinfo = get_fs_info (fs_type); + if (fsinfo != NULL) { + switch (op) { + case BD_FS_RESIZE: + op_name = "Resizing"; + exec_util = fsinfo->resize_util; + break; + case BD_FS_REPAIR: + op_name = "Repairing"; + exec_util = fsinfo->repair_util; + break; + case BD_FS_CHECK: + op_name = "Checking"; + exec_util = fsinfo->check_util; + break; + case BD_FS_LABEL: + op_name = "Setting the label of"; + exec_util = fsinfo->label_util; + break; + } + } + + if (fsinfo == NULL || exec_util == NULL) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_SUPPORTED, + "%s filesystem '%s' is not supported.", op_name, fs_type); + return FALSE; + } + + if (mode != NULL) + *mode = fsinfo->resize_mode; + + if (strlen(exec_util) == 0) { /* empty string if no util needed */ + return TRUE; + } + + ret = bd_utils_check_util_version (exec_util, NULL, "", NULL, NULL); + if (!ret && required_utility != NULL) + *required_utility = g_strdup (exec_util); + + return ret; +} + +/** + * bd_fs_can_resize: + * @type: the filesystem type to be tested for installed resize support + * @mode: (out): flags for allowed resizing (i.e. growing/shrinking support for online/offline) + * @required_utility: (out) (transfer full): the utility binary which is required for resizing (if missing i.e. returns FALSE but no error) + * @error: (out): place to store error (if any) + * + * Searches for the required utility to resize the given filesystem and returns whether + * it is installed. The mode flags indicate if growing and/or shrinking resize is available if + * mounted/unmounted. + * Unknown filesystems or filesystems which do not support resizing result in errors. + * + * Returns: whether filesystem resize is available + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY + */ +gboolean bd_fs_can_resize (const gchar *type, BDFsResizeFlags *mode, gchar **required_utility, GError **error) { + return query_fs_operation (type, BD_FS_RESIZE, required_utility, mode, error); +} + +/** + * bd_fs_can_check: + * @type: the filesystem type to be tested for installed consistency check support + * @required_utility: (out) (transfer full): the utility binary which is required for checking (if missing i.e. returns FALSE but no error) + * @error: (out): place to store error (if any) + * + * Searches for the required utility to check the given filesystem and returns whether + * it is installed. + * Unknown filesystems or filesystems which do not support checking result in errors. + * + * Returns: whether filesystem check is available + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY + */ +gboolean bd_fs_can_check (const gchar *type, gchar **required_utility, GError **error) { + return query_fs_operation (type, BD_FS_CHECK, required_utility, NULL, error); +} + +/** + * bd_fs_can_repair: + * @type: the filesystem type to be tested for installed repair support + * @required_utility: (out) (transfer full): the utility binary which is required for repairing (if missing i.e. return FALSE but no error) + * @error: (out): place to store error (if any) + * + * Searches for the required utility to repair the given filesystem and returns whether + * it is installed. + * Unknown filesystems or filesystems which do not support reparing result in errors. + * + * Returns: whether filesystem repair is available + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY + */ +gboolean bd_fs_can_repair (const gchar *type, gchar **required_utility, GError **error) { + return query_fs_operation (type, BD_FS_REPAIR, required_utility, NULL, error); +} + +/** + * bd_fs_can_set_label: + * @type: the filesystem type to be tested for installed label support + * @required_utility: (out) (transfer full): the utility binary which is required for relabeling (if missing i.e. return FALSE but no error) + * @error: (out): place to store error (if any) + * + * Searches for the required utility to set the label of the given filesystem and returns whether + * it is installed. + * Unknown filesystems or filesystems which do not support setting the label result in errors. + * + * Returns: whether setting filesystem label is available + * + * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY + */ +gboolean bd_fs_can_set_label (const gchar *type, gchar **required_utility, GError **error) { + return query_fs_operation (type, BD_FS_LABEL, required_utility, NULL, error); +} diff -Nru libblockdev-2.14/src/plugins/fs/generic.h libblockdev-2.16/src/plugins/fs/generic.h --- libblockdev-2.14/src/plugins/fs/generic.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/generic.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,27 @@ +#include + +#ifndef BD_FS_GENERIC +#define BD_FS_GENERIC + +gboolean bd_fs_wipe (const gchar *device, gboolean all, GError **error); +gboolean bd_fs_clean (const gchar *device, GError **error); +gchar* bd_fs_get_fstype (const gchar *device, GError **error); + +gboolean bd_fs_resize (const gchar *device, guint64 new_size, GError **error); +gboolean bd_fs_repair (const gchar *device, GError **error); +gboolean bd_fs_check (const gchar *device, GError **error); +gboolean bd_fs_set_label (const gchar *device, const gchar *label, GError **error); + +typedef enum { + BD_FS_OFFLINE_SHRINK = 1 << 1, + BD_FS_OFFLINE_GROW = 1 << 2, + BD_FS_ONLINE_SHRINK = 1 << 3, + BD_FS_ONLINE_GROW = 1 << 4 +} BDFsResizeFlags; + +gboolean bd_fs_can_resize (const gchar *type, BDFsResizeFlags *mode, gchar **required_utility, GError **error); +gboolean bd_fs_can_check (const gchar *type, gchar **required_utility, GError **error); +gboolean bd_fs_can_repair (const gchar *type, gchar **required_utility, GError **error); +gboolean bd_fs_can_set_label (const gchar *type, gchar **required_utility, GError **error); + +#endif /* BD_FS_GENERIC */ diff -Nru libblockdev-2.14/src/plugins/fs/Makefile.am libblockdev-2.16/src/plugins/fs/Makefile.am --- libblockdev-2.14/src/plugins/fs/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/Makefile.am 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,25 @@ +AUTOMAKE_OPTIONS = subdir-objects + +lib_LTLIBRARIES = libbd_fs.la + +libbd_fs_la_CFLAGS = $(GLIB_CFLAGS) $(BLKID_CFLAGS) $(PARTED_CFLAGS) $(PARTED_FS_CFLAGS) $(MOUNT_CFLAGS) -Wall -Wextra -Werror +libbd_fs_la_LIBADD = $(GLIB_LIBS) $(BLKID_LIBS) $(PARTED_LIBS) $(PARTED_FS_LIBS) $(MOUNT_LIBS) ${builddir}/../../utils/libbd_utils.la ${builddir}/../libbd_part_err.la +libbd_fs_la_LDFLAGS = -L${srcdir}/../../utils/ -version-info 2:0:0 -Wl,--no-undefined +libbd_fs_la_CPPFLAGS = -I${builddir}/../../../include/ -I${srcdir}/../ +libbd_fs_la_SOURCES = ../check_deps.c ../check_deps.h \ + ../fs.c ../fs.h \ + common.c common.h \ + ext.c ext.h \ + generic.c generic.h \ + mount.c mount.h \ + ntfs.c ntfs.h \ + vfat.c vfat.h \ + xfs.c xfs.h + +libincludefsdir = $(includedir)/blockdev/fs/ +libincludefs_HEADERS = ext.h \ + generic.h \ + mount.h \ + ntfs.h \ + vfat.h \ + xfs.h diff -Nru libblockdev-2.14/src/plugins/fs/mount.c libblockdev-2.16/src/plugins/fs/mount.c --- libblockdev-2.14/src/plugins/fs/mount.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/mount.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,756 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#define _GNU_SOURCE +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "fs.h" +#include "mount.h" + +#define MOUNT_ERR_BUF_SIZE 1024 + +typedef struct MountArgs { + const gchar *mountpoint; + const gchar *device; + const gchar *fstype; + const gchar *options; + const gchar *spec; + gboolean lazy; + gboolean force; +} MountArgs; + +typedef gboolean (*MountFunc) (MountArgs *args, GError **error); + +static gboolean do_mount (MountArgs *args, GError **error); + +#ifndef LIBMOUNT_NEW_ERR_API +static void parse_unmount_error_old (struct libmnt_context *cxt, int rc, const gchar *spec, GError **error) { + int syscall_errno = 0; + + if (mnt_context_syscall_called (cxt)) { + syscall_errno = mnt_context_get_syscall_errno (cxt); + switch (syscall_errno) { + case EBUSY: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Target busy."); + break; + case EINVAL: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Not a mount point."); + break; + case EPERM: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, + "Operation not permitted."); + break; + default: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Unmount syscall failed: %d.", syscall_errno); + break; + } + } else { + if (rc == -EPERM) { + if (mnt_context_tab_applied (cxt)) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, + "Operation not permitted."); + else + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Not mounted."); + } else { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to unmount %s.", spec); + } + } + return; +} +#else +static void parse_unmount_error_new (struct libmnt_context *cxt, int rc, const gchar *spec, GError **error) { + int ret = 0; + int syscall_errno = 0; + char buf[MOUNT_ERR_BUF_SIZE] = {0}; + gboolean permission = FALSE; + + ret = mnt_context_get_excode (cxt, rc, buf, MOUNT_ERR_BUF_SIZE - 1); + if (ret != 0) { + /* check whether the call failed because of lack of permission */ + if (mnt_context_syscall_called (cxt)) { + syscall_errno = mnt_context_get_syscall_errno (cxt); + permission = syscall_errno == EPERM; + } else + permission = ret == MNT_EX_USAGE && mnt_context_tab_applied (cxt); + + if (permission) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, + "Operation not permitted."); + else { + if (*buf == '\0') + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Unknow error when unmounting %s", spec); + else + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "%s", buf); + } + } else + /* mnt_context_umount returned non-zero, but mnt_context_get_excode + * returned zero -- this should never happen, but just in case set error + * to something sane here + */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Unknow error when unmounting %s", spec); + return; +} +#endif + +static gboolean do_unmount (MountArgs *args, GError **error) { + struct libmnt_context *cxt = NULL; + int ret = 0; + + cxt = mnt_new_context (); + + if (mnt_context_set_target (cxt, args->spec) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set '%s' as target for umount", args->spec); + mnt_free_context(cxt); + return FALSE; + } + + if (args->lazy) { + if (mnt_context_enable_lazy (cxt, TRUE) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set lazy unmount for '%s'", args->spec); + mnt_free_context(cxt); + return FALSE; + } + } + + if (args->force) { + if (mnt_context_enable_force (cxt, TRUE) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set force unmount for '%s'", args->spec); + mnt_free_context(cxt); + return FALSE; + } + } + + ret = mnt_context_umount (cxt); + if (ret != 0) { +#ifdef LIBMOUNT_NEW_ERR_API + parse_unmount_error_new (cxt, ret, args->spec, error); +#else + parse_unmount_error_old (cxt, ret, args->spec, error); +#endif + mnt_free_context(cxt); + return FALSE; + } + + mnt_free_context(cxt); + return TRUE; +} + +#ifndef LIBMOUNT_NEW_ERR_API +static gboolean parse_mount_error_old (struct libmnt_context *cxt, int rc, MountArgs *args, GError **error) { + int syscall_errno = 0; + unsigned long mflags = 0; + + if (mnt_context_get_mflags (cxt, &mflags) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get options from string '%s'.", args->options); + return FALSE; + } + + if (mnt_context_syscall_called (cxt) == 1) { + syscall_errno = mnt_context_get_syscall_errno (cxt); + switch (syscall_errno) { + case EBUSY: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Source is already mounted or target is busy."); + break; + case EINVAL: + if (mflags & MS_REMOUNT) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Remount attempted, but %s is not mounted at %s.", args->device, args->mountpoint); + else if (mflags & MS_MOVE) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Move attempted, but %s is not a mount point.", args->device); + else + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Wrong fs type, %s has an invalid superblock or missing helper program.", args->device); + break; + case EPERM: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, + "Operation not permitted."); + break; + case ENOTBLK: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "%s is not a block device.", args->device); + break; + case ENOTDIR: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "%s is not a directory.", args->mountpoint); + break; + case ENODEV: + if (args->fstype == NULL || strlen (args->fstype) == 0) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Filesystem type not specified"); + else + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Filesystem type %s not configured in kernel.", args->fstype); + break; + case EROFS: + case EACCES: + if (mflags & MS_RDONLY) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Cannot mount %s read-only.", args->device); + break; + } else if (args->options && (mnt_optstr_get_option (args->options, "rw", NULL, NULL) == 0)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "%s is write-protected but `rw' option given.", args->device); + break; + } else if (mflags & MS_BIND) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Mount %s on %s failed.", args->device, args->mountpoint); + break; + } + /* new versions of libmount do this automatically */ + else { + MountArgs ro_args; + gboolean success = FALSE; + + ro_args.device = args->device; + ro_args.mountpoint = args->mountpoint; + ro_args.fstype = args->fstype; + if (!args->options) + ro_args.options = g_strdup ("ro"); + else + ro_args.options = g_strdup_printf ("%s,ro", args->options); + + success = do_mount (&ro_args, error); + + g_free ((gchar*) ro_args.options); + + return success; + } + default: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Mount syscall failed: %d.", syscall_errno); + break; + } + } else { + switch (rc) { + case -EPERM: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, + "Only root can mount %s.", args->device); + break; + case -EBUSY: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "%s is already mounted.", args->device); + break; + /* source or target explicitly defined and not found in fstab */ + case -MNT_ERR_NOFSTAB: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Can't find %s in %s.", args->device ? args->device : args->mountpoint, mnt_get_fstab_path ()); + break; + case -MNT_ERR_MOUNTOPT: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to parse mount options"); + break; + case -MNT_ERR_NOSOURCE: + if (args->device) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Can't find %s.", args->device); + else + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Mount source not defined."); + break; + case -MNT_ERR_LOOPDEV: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to setup loop device"); + break; + case -MNT_ERR_NOFSTYPE: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Filesystem type not specified"); + break; + default: + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to mount %s.", args->device ? args->device : args->mountpoint); + break; + } + } + + return FALSE; +} + +#else +static void parse_mount_error_new (struct libmnt_context *cxt, int rc, MountArgs *args, GError **error) { + int ret = 0; + int syscall_errno = 0; + char buf[MOUNT_ERR_BUF_SIZE] = {0}; + gboolean permission = FALSE; + + ret = mnt_context_get_excode (cxt, rc, buf, MOUNT_ERR_BUF_SIZE - 1); + if (ret != 0) { + /* check whether the call failed because of lack of permission */ + if (mnt_context_syscall_called (cxt)) { + syscall_errno = mnt_context_get_syscall_errno (cxt); + permission = syscall_errno == EPERM; + } else + permission = ret == MNT_EX_USAGE && mnt_context_tab_applied (cxt); + + if (permission) + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, + "Operation not permitted."); + else { + if (*buf == '\0') + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Unknow error when mounting %s", args->device ? args->device : args->mountpoint); + else + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "%s", buf); + } + } + + return; +} +#endif + +static gboolean do_mount (MountArgs *args, GError **error) { + struct libmnt_context *cxt = NULL; + int ret = 0; + gboolean success = FALSE; + + cxt = mnt_new_context (); + + if (!args->mountpoint && !args->device) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "You must specify at least one of: mount point, device."); + mnt_free_context(cxt); + return FALSE; + } + + if (args->mountpoint) { + if (mnt_context_set_target (cxt, args->mountpoint) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set '%s' as target for mount", args->mountpoint); + mnt_free_context(cxt); + return FALSE; + } + } + + if (args->device) { + if (mnt_context_set_source (cxt, args->device) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set '%s' as source for mount", args->device); + mnt_free_context(cxt); + return FALSE; + } + } + + if (args->fstype) { + if (mnt_context_set_fstype (cxt, args->fstype) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set '%s' as fstype for mount", args->fstype); + mnt_free_context(cxt); + return FALSE; + } + } + + if (args->options) { + if (mnt_context_set_options (cxt, args->options) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set '%s' as options for mount", args->options); + mnt_free_context(cxt); + return FALSE; + } + } + +#ifdef LIBMOUNT_NEW_ERR_API + /* we don't want libmount to try RDONLY mounts if we were explicitly given the "rw" option */ + if (args->options && (mnt_optstr_get_option (args->options, "rw", NULL, NULL) == 0)) + mnt_context_enable_rwonly_mount (cxt, TRUE); +#endif + + ret = mnt_context_mount (cxt); + + if (ret != 0) { +#ifdef LIBMOUNT_NEW_ERR_API + parse_mount_error_new (cxt, ret, args, error); + success = FALSE; +#else + success = parse_mount_error_old (cxt, ret, args, error); +#endif + } else + success = TRUE; + + mnt_free_context(cxt); + return success; +} + +static gboolean set_uid (uid_t uid, GError **error) { + if (setresuid (uid, -1, -1) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error setting uid: %m"); + return FALSE; + } + + return TRUE; +} + +static gboolean set_gid (gid_t gid, GError **error) { + if (setresgid (gid, -1, -1) != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error setting gid: %m"); + return FALSE; + } + + return TRUE; +} + +static gboolean run_as_user (MountFunc func, MountArgs *args, uid_t run_as_uid, gid_t run_as_gid, GError ** error) { + uid_t current_uid = -1; + gid_t current_gid = -1; + pid_t pid = -1; + pid_t wpid = -1; + int pipefd[2]; + int status = 0; + GIOChannel *channel = NULL; + GError *local_error = NULL; + gchar *error_msg = NULL; + gsize msglen = 0; + + current_uid = getuid (); + current_gid = getgid (); + + if (pipe(pipefd) == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error creating pipe."); + return FALSE; + } + + pid = fork (); + + if (pid == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error forking."); + return FALSE; + } else if (pid == 0) { + close (pipefd[0]); + + if (run_as_gid != current_gid) { + if (!set_gid (run_as_gid, error)) { + if (write(pipefd[1], (*error)->message, strlen((*error)->message)) < 0) + _exit (BD_FS_ERROR_PIPE); + else + _exit ((*error)->code); + } + } + + if (run_as_uid != current_uid) { + if (!set_uid (run_as_uid, error)) { + if (write(pipefd[1], (*error)->message, strlen((*error)->message)) < 0) + _exit (BD_FS_ERROR_PIPE); + else + _exit ((*error)->code); + } + } + + if (!func (args, error)) { + if (write(pipefd[1], (*error)->message, strlen((*error)->message)) < 0) + _exit (BD_FS_ERROR_PIPE); + else + _exit ((*error)->code); + } + + _exit (EXIT_SUCCESS); + + } else { + close (pipefd[1]); + + do { + wpid = waitpid (pid, &status, WUNTRACED | WCONTINUED); + if (wpid == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error while waiting for process."); + return FALSE; + } + + if (WIFEXITED (status)) { + if (WEXITSTATUS (status) != EXIT_SUCCESS) { + if (WEXITSTATUS (status) == BD_FS_ERROR_PIPE) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error while reading error."); + return FALSE; + } + + channel = g_io_channel_unix_new (pipefd[0]); + if (g_io_channel_read_to_end (channel, &error_msg, &msglen, &local_error) != G_IO_STATUS_NORMAL) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error while reading error: %s (%d)", + local_error->message, local_error->code); + g_clear_error (&local_error); + g_io_channel_unref (channel); + return FALSE; + } + + if (g_io_channel_shutdown (channel, TRUE, &local_error) == G_IO_STATUS_ERROR) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Error shutting down GIO channel: %s (%d)", + local_error->message, local_error->code); + g_clear_error (&local_error); + g_io_channel_unref (channel); + return FALSE; + } + + if (WEXITSTATUS (status) > BD_FS_ERROR_AUTH) + g_set_error_literal (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + error_msg); + else + g_set_error_literal (error, BD_FS_ERROR, WEXITSTATUS (status), + error_msg); + + g_io_channel_unref (channel); + return FALSE; + } else + return TRUE; + } else if (WIFSIGNALED (status)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Killed by signal %d.", WTERMSIG(status)); + return FALSE; + } + + } while (!WIFEXITED (status) && !WIFSIGNALED (status)); + } + + return FALSE; +} + +/** + * bd_fs_unmount: + * @spec: mount point or device to unmount + * @lazy: enable/disable lazy unmount + * @force: enable/disable force unmount + * @extra: (allow-none) (array zero-terminated=1): extra options for the unmount + * currently only 'run_as_uid' + * and 'run_as_gid' are supported + * value must be a valid non zero + * uid (gid) + * @error: (out): place to store error (if any) + * + * Returns: whether @spec was successfully unmounted or not + * + * Tech category: %BD_FS_TECH_GENERIC (no mode, ignored) + */ +gboolean bd_fs_unmount (const gchar *spec, gboolean lazy, gboolean force, const BDExtraArg **extra, GError **error) { + uid_t run_as_uid = -1; + gid_t run_as_gid = -1; + uid_t current_uid = -1; + gid_t current_gid = -1; + const BDExtraArg **extra_p = NULL; + MountArgs args; + + args.spec = spec; + args.lazy = lazy; + args.force = force; + + current_uid = getuid (); + run_as_uid = current_uid; + + current_gid = getgid (); + run_as_gid = current_gid; + + if (extra) { + for (extra_p=extra; *extra_p; extra_p++) { + if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_uid") == 0)) { + run_as_uid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); + + /* g_ascii_strtoull returns 0 in case of error */ + if (run_as_uid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Invalid specification of UID: '%s'", (*extra_p)->val); + return FALSE; + } + } else if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_gid") == 0)) { + run_as_gid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); + + /* g_ascii_strtoull returns 0 in case of error */ + if (run_as_gid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Invalid specification of GID: '%s'", (*extra_p)->val); + return FALSE; + } + } else { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Unsupported argument for unmount: '%s'", (*extra_p)->opt); + return FALSE; + } + } + } + + if (run_as_uid != current_uid || run_as_gid != current_gid) { + return run_as_user ((MountFunc) do_unmount, &args, run_as_uid, run_as_gid, error); + } else + return do_unmount (&args, error); + + return TRUE; +} + +/** + * bd_fs_mount: + * @device: (allow-none): device to mount, if not specified @mountpoint entry + * from fstab will be used + * @mountpoint: (allow-none): mountpoint for @device, if not specified @device + * entry from fstab will be used + * @fstype: (allow-none): filesystem type + * @options: (allow-none): comma delimited options for mount + * @extra: (allow-none) (array zero-terminated=1): extra options for the mount + * currently only 'run_as_uid' + * and 'run_as_gid' are supported + * value must be a valid non zero + * uid (gid) + * @error: (out): place to store error (if any) + * + * Returns: whether @device (or @mountpoint) was successfully mounted or not + * + * Tech category: %BD_FS_TECH_MOUNT (no mode, ignored) + */ +gboolean bd_fs_mount (const gchar *device, const gchar *mountpoint, const gchar *fstype, const gchar *options, const BDExtraArg **extra, GError **error) { + uid_t run_as_uid = -1; + gid_t run_as_gid = -1; + uid_t current_uid = -1; + gid_t current_gid = -1; + const BDExtraArg **extra_p = NULL; + MountArgs args; + + args.device = device; + args.mountpoint = mountpoint; + args.fstype = fstype; + args.options = options; + + current_uid = getuid (); + run_as_uid = current_uid; + + current_gid = getgid (); + run_as_gid = current_gid; + + if (extra) { + for (extra_p=extra; *extra_p; extra_p++) { + if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_uid") == 0)) { + run_as_uid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); + + /* g_ascii_strtoull returns 0 in case of error */ + if (run_as_uid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Invalid specification of UID: '%s'", (*extra_p)->val); + return FALSE; + } + } else if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_gid") == 0)) { + run_as_gid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); + + /* g_ascii_strtoull returns 0 in case of error */ + if (run_as_gid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Invalid specification of GID: '%s'", (*extra_p)->val); + return FALSE; + } + } else { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Unsupported argument for unmount: '%s'", (*extra_p)->opt); + return FALSE; + } + } + } + + if (run_as_uid != current_uid || run_as_gid != current_gid) { + return run_as_user ((MountFunc) do_mount, &args, run_as_uid, run_as_gid, error); + } else + return do_mount (&args, error); + + return TRUE; +} + +/** + * bd_fs_get_mountpoint: + * @device: device to find mountpoint for + * @error: (out): place to store error (if any) + * + * Get mountpoint for @device. If @device is mounted multiple times only + * one mountpoint will be returned. + * + * Returns: (transfer full): mountpoint for @device, %NULL in case device is + * not mounted or in case of an error (@error is set + * in this case) + * + * Tech category: %BD_FS_TECH_MOUNT (no mode, ignored) + */ +gchar* bd_fs_get_mountpoint (const gchar *device, GError **error) { + struct libmnt_table *table = NULL; + struct libmnt_fs *fs = NULL; + struct libmnt_cache *cache = NULL; + gint ret = 0; + gchar *mountpoint = NULL; + const gchar *target = NULL; + + table = mnt_new_table (); + cache = mnt_new_cache (); + + ret = mnt_table_set_cache (table, cache); + if (ret != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to set cache for mount info table."); + mnt_free_table (table); + return NULL; + } + + ret = mnt_table_parse_mtab (table, NULL); + if (ret != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to parse mount info."); + mnt_free_table (table); + mnt_free_cache (cache); + return NULL; + } + + fs = mnt_table_find_source (table, device, MNT_ITER_FORWARD); + if (!fs) { + mnt_free_table (table); + mnt_free_cache (cache); + return NULL; + } + + target = mnt_fs_get_target (fs); + if (!target) { + mnt_free_fs (fs); + mnt_free_table (table); + mnt_free_cache (cache); + return NULL; + } + + mountpoint = g_strdup (target); + mnt_free_fs (fs); + mnt_free_table (table); + mnt_free_cache (cache); + return mountpoint; +} diff -Nru libblockdev-2.14/src/plugins/fs/mount.h libblockdev-2.16/src/plugins/fs/mount.h --- libblockdev-2.14/src/plugins/fs/mount.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/mount.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,11 @@ +#include +#include + +#ifndef BD_FS_MOUNT +#define BD_FS_MOUNT + +gboolean bd_fs_unmount (const gchar *spec, gboolean lazy, gboolean force, const BDExtraArg **extra, GError **error); +gboolean bd_fs_mount (const gchar *device, const gchar *mountpoint, const gchar *fstype, const gchar *options, const BDExtraArg **extra, GError **error); +gchar* bd_fs_get_mountpoint (const gchar *device, GError **error); + +#endif /* BD_FS_MOUNT */ diff -Nru libblockdev-2.14/src/plugins/fs/ntfs.c libblockdev-2.16/src/plugins/fs/ntfs.c --- libblockdev-2.14/src/plugins/fs/ntfs.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/ntfs.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#include +#include +#include + +#include "ntfs.h" +#include "fs.h" +#include "common.h" + +static volatile guint avail_deps = 0; +static GMutex deps_check_lock; + +#define DEPS_MKNTFS 0 +#define DEPS_MKNTFS_MASK (1 << DEPS_MKNTFS) +#define DEPS_NTFSFIX 1 +#define DEPS_NTFSFIX_MASK (1 << DEPS_NTFSFIX) +#define DEPS_NTFSRESIZE 2 +#define DEPS_NTFSRESIZE_MASK (1 << DEPS_NTFSRESIZE) +#define DEPS_NTFSLABEL 3 +#define DEPS_NTFSLABEL_MASK (1 << DEPS_NTFSLABEL) +#define DEPS_NTFSCLUSTER 4 +#define DEPS_NTFSCLUSTER_MASK (1 << DEPS_NTFSCLUSTER) + +#define DEPS_LAST 5 + +static UtilDep deps[DEPS_LAST] = { + {"mkntfs", NULL, NULL, NULL}, + {"ntfsfix", NULL, NULL, NULL}, + {"ntfsresize", NULL, NULL, NULL}, + {"ntfslabel", NULL, NULL, NULL}, + {"ntfscluster", NULL, NULL, NULL}, +}; + +static guint32 fs_mode_util[BD_FS_MODE_LAST+1] = { + /* mkfs wipe check repair set-label query resize */ + DEPS_MKNTFS_MASK, 0, DEPS_NTFSFIX_MASK, DEPS_NTFSFIX_MASK, DEPS_NTFSLABEL_MASK, DEPS_NTFSCLUSTER_MASK, DEPS_NTFSRESIZE_MASK +}; + +#define UNUSED __attribute__((unused)) + +/** + * bd_fs_ntfs_is_tech_avail: + * @tech: the queried tech + * @mode: a bit mask of queried modes of operation (#BDFSTechMode) for @tech + * @error: (out): place to store error (details about why the @tech-@mode combination is not available) + * + * Returns: whether the @tech-@mode combination is available -- supported by the + * plugin implementation and having all the runtime dependencies available + */ +gboolean bd_fs_ntfs_is_tech_avail (BDFSTech tech UNUSED, guint64 mode, GError **error) { + guint32 required = 0; + guint i = 0; + for (i = 0; i <= BD_FS_MODE_LAST; i++) + if (mode & (1 << i)) + required |= fs_mode_util[i]; + + return check_deps (&avail_deps, required, deps, DEPS_LAST, &deps_check_lock, error); +} + +/** + * bd_fs_ntfs_info_copy: (skip) + * + * Creates a new copy of @data. + */ +BDFSNtfsInfo* bd_fs_ntfs_info_copy (BDFSNtfsInfo *data) { + BDFSNtfsInfo *ret = g_new0 (BDFSNtfsInfo, 1); + + ret->size = data->size; + ret->free_space = data->free_space; + + return ret; +} + +/** + * bd_fs_ntfs_info_free: (skip) + * + * Frees @data. + */ +void bd_fs_ntfs_info_free (BDFSNtfsInfo *data) { + g_free (data); +} + +/** + * bd_fs_ntfs_mkfs: + * @device: the device to create a new ntfs fs on + * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now + * passed to the 'mkntfs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether a new NTFS fs was successfully created on @device or not + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_MKFS + */ +gboolean bd_fs_ntfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { + const gchar *args[5] = {"mkntfs", "-f", "-F", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_MKNTFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, extra, error); +} + +/** + * bd_fs_ntfs_wipe: + * @device: the device to wipe an ntfs signature from + * @error: (out): place to store error (if any) + * + * Returns: whether an ntfs signature was successfully wiped from the @device or not + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_ntfs_wipe (const gchar *device, GError **error) { + return wipe_fs (device, "ntfs", TRUE, error); +} + +/** + * bd_fs_ntfs_check: + * @device: the device containing the file system to check + * @error: (out): place to store error (if any) + * + * Returns: whether an ntfs file system on the @device is clean or not + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_ntfs_check (const gchar *device, GError **error) { + const gchar *args[4] = {"ntfsfix", "-n", device, NULL}; + gint status = 0; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_NTFSFIX_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + ret = bd_utils_exec_and_report_status_error (args, NULL, &status, error); + if (!ret && (status == 1)) { + /* no error should be reported for exit code 1 -- Recoverable errors have been detected */ + g_clear_error (error); + } + return ret; +} + +/** + * bd_fs_ntfs_repair: + * @device: the device containing the file system to repair + * @error: (out): place to store error (if any) + * + * Returns: whether an NTFS file system on the @device was successfully repaired + * (if needed) or not (error is set in that case) + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_ntfs_repair (const gchar *device, GError **error) { + const gchar *args[4] = {"ntfsfix", "-d", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_NTFSFIX_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, NULL, error); +} + +/** + * bd_fs_ntfs_set_label: + * @device: the device containing the file system to set the label for + * @label: label to set + * @error: (out): place to store error (if any) + * + * Returns: whether the label of the NTFS file system on the @device was + * successfully set or not + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_ntfs_set_label (const gchar *device, const gchar *label, GError **error) { + const gchar *args[4] = {"ntfslabel", device, label, NULL}; + + if (!check_deps (&avail_deps, DEPS_NTFSLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, NULL, error); +} + +/** + * bd_fs_ntfs_resize: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system in bytes (if 0, the file system + * is adapted to the underlying block device) + * @error: (out): place to store error (if any) + * + * Returns: whether the file system on @device was successfully resized or not + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_ntfs_resize (const gchar *device, guint64 new_size, GError **error) { + const gchar *args[5] = {"ntfsresize", NULL, NULL, NULL, NULL}; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_NTFSRESIZE_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + if (new_size != 0) { + args[1] = "-s"; + args[2] = g_strdup_printf ("%"G_GUINT64_FORMAT, new_size); + args[3] = device; + } else { + args[1] = device; + } + ret = bd_utils_exec_and_report_error (args, NULL, error); + + g_free ((gchar *) args[2]); + return ret; +} + +/** + * bd_fs_ntfs_get_info: + * @device: the device containing the file system to get info for (device must + not be mounted, trying to get info for a mounted device will result + in an error) + * @error: (out): place to store error (if any) + * + * Returns: (transfer full): information about the file system on @device or + * %NULL in case of error + * + * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_QUERY + */ +BDFSNtfsInfo* bd_fs_ntfs_get_info (const gchar *device, GError **error) { + const gchar *args[3] = {"ntfscluster", device, NULL}; + gboolean success = FALSE; + gchar *output = NULL; + BDFSNtfsInfo *ret = NULL; + gchar **lines = NULL; + gchar **line_p = NULL; + gchar *val_start = NULL; + g_autofree gchar* mountpoint = NULL; + + if (!check_deps (&avail_deps, DEPS_NTFSCLUSTER_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + mountpoint = bd_fs_get_mountpoint (device, error); + if (mountpoint != NULL) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_MOUNTED, + "Can't get NTFS file system information for '%s': Device is mounted.", device); + return NULL; + } else { + if (*error != NULL) { + g_prefix_error (error, "Error when trying to get mountpoint for '%s': ", device); + return NULL; + } + } + + success = bd_utils_exec_and_capture_output (args, NULL, &output, error); + if (!success) + /* error is already populated */ + return FALSE; + + ret = g_new0 (BDFSNtfsInfo, 1); + lines = g_strsplit (output, "\n", 0); + g_free (output); + line_p = lines; + /* find the beginning of the (data) section we are interested in */ + while (line_p && *line_p && !g_str_has_prefix (*line_p, "bytes per volume")) + line_p++; + if (!line_p || !(*line_p)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NTFS file system information"); + g_strfreev (lines); + bd_fs_ntfs_info_free (ret); + return FALSE; + } + + /* extract data from something like this: "bytes per volume : 998240256" */ + val_start = strchr (*line_p, ':'); + val_start++; + ret->size = g_ascii_strtoull (val_start, NULL, 0); + + while (line_p && *line_p && !g_str_has_prefix (*line_p, "bytes of free space")) + line_p++; + if (!line_p || !(*line_p)) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NTFS file system information"); + g_strfreev (lines); + bd_fs_ntfs_info_free (ret); + return FALSE; + } + + /* extract data from something like this: "bytes of free space : 992759808" */ + val_start = strchr (*line_p, ':'); + val_start++; + ret->free_space = g_ascii_strtoull (val_start, NULL, 0); + + g_strfreev (lines); + + return ret; +} diff -Nru libblockdev-2.14/src/plugins/fs/ntfs.h libblockdev-2.16/src/plugins/fs/ntfs.h --- libblockdev-2.14/src/plugins/fs/ntfs.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/ntfs.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,23 @@ +#include +#include + +#ifndef BD_FS_NTFS +#define BD_FS_NTFS + +typedef struct BDFSNtfsInfo { + guint64 size; + guint64 free_space; +} BDFSNtfsInfo; + +BDFSNtfsInfo* bd_fs_ntfs_info_copy (BDFSNtfsInfo *data); +void bd_fs_ntfs_info_free (BDFSNtfsInfo *data); + +gboolean bd_fs_ntfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_ntfs_wipe (const gchar *device, GError **error); +gboolean bd_fs_ntfs_check (const gchar *device, GError **error); +gboolean bd_fs_ntfs_repair (const gchar *device, GError **error); +gboolean bd_fs_ntfs_set_label (const gchar *device, const gchar *label, GError **error); +BDFSNtfsInfo* bd_fs_ntfs_get_info (const gchar *device, GError **error); +gboolean bd_fs_ntfs_resize (const gchar *device, guint64 new_size, GError **error); + +#endif /* BD_FS_NTFS */ diff -Nru libblockdev-2.14/src/plugins/fs/vfat.c libblockdev-2.16/src/plugins/fs/vfat.c --- libblockdev-2.14/src/plugins/fs/vfat.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/vfat.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#include +#include +#include +#include +#include +#include + +#include "vfat.h" +#include "fs.h" +#include "common.h" + +static volatile guint avail_deps = 0; +static GMutex deps_check_lock; + +#define DEPS_MKFSVFAT 0 +#define DEPS_MKFSVFAT_MASK (1 << DEPS_MKFSVFAT) +#define DEPS_FATLABEL 1 +#define DEPS_FATLABEL_MASK (1 << DEPS_FATLABEL) +#define DEPS_FSCKVFAT 2 +#define DEPS_FSCKVFAT_MASK (1 << DEPS_FSCKVFAT) + +#define DEPS_LAST 3 + +static UtilDep deps[DEPS_LAST] = { + {"mkfs.vfat", NULL, NULL, NULL}, + {"fatlabel", NULL, NULL, NULL}, + {"fsck.vfat", NULL, NULL, NULL}, +}; + +static guint32 fs_mode_util[BD_FS_MODE_LAST+1] = { + /* mkfs wipe check repair set-label query resize */ + DEPS_MKFSVFAT_MASK, 0, DEPS_FSCKVFAT_MASK, DEPS_FSCKVFAT_MASK, DEPS_FATLABEL_MASK, DEPS_FSCKVFAT_MASK, 0 +}; + +#define UNUSED __attribute__((unused)) + +/** + * bd_fs_vfat_is_tech_avail: + * @tech: the queried tech + * @mode: a bit mask of queried modes of operation (#BDFSTechMode) for @tech + * @error: (out): place to store error (details about why the @tech-@mode combination is not available) + * + * Returns: whether the @tech-@mode combination is available -- supported by the + * plugin implementation and having all the runtime dependencies available + */ +gboolean bd_fs_vfat_is_tech_avail (BDFSTech tech UNUSED, guint64 mode, GError **error) { + guint32 required = 0; + guint i = 0; + for (i = 0; i <= BD_FS_MODE_LAST; i++) + if (mode & (1 << i)) + required |= fs_mode_util[i]; + + return check_deps (&avail_deps, required, deps, DEPS_LAST, &deps_check_lock, error); +} + +/** + * bd_fs_vfat_info_copy: (skip) + * + * Creates a new copy of @data. + */ +BDFSVfatInfo* bd_fs_vfat_info_copy (BDFSVfatInfo *data) { + BDFSVfatInfo *ret = g_new0 (BDFSVfatInfo, 1); + + ret->label = g_strdup (data->label); + ret->uuid = g_strdup (data->uuid); + ret->cluster_size = data->cluster_size; + ret->cluster_count = data->cluster_count; + ret->free_cluster_count = data->free_cluster_count; + + return ret; +} + +/** + * bd_fs_vfat_info_free: (skip) + * + * Frees @data. + */ +void bd_fs_vfat_info_free (BDFSVfatInfo *data) { + g_free (data->label); + g_free (data->uuid); + g_free (data); +} + +/** + * set_parted_error: (skip) + * + * Set error from the parted error stored in 'error_msg'. In case there is none, + * the error is set up with an empty string. Otherwise it is set up with the + * parted's error message and is a subject to later g_prefix_error() call. + * + * Returns: whether there was some message from parted or not + */ +static gboolean set_parted_error (GError **error, BDFsError type) { + gchar *error_msg = NULL; + error_msg = bd_get_error_msg (); + if (error_msg) { + g_set_error (error, BD_FS_ERROR, type, + " (%s)", error_msg); + g_free (error_msg); + error_msg = NULL; + return TRUE; + } else { + g_set_error_literal (error, BD_FS_ERROR, type, ""); + return FALSE; + } +} + +/** + * bd_fs_vfat_mkfs: + * @device: the device to create a new vfat fs on + * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now + * passed to the 'mkfs.vfat' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether a new vfat fs was successfully created on @device or not + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_MKFS + */ +gboolean bd_fs_vfat_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { + const gchar *args[4] = {"mkfs.vfat", "-I", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_MKFSVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, extra, error); +} + +/** + * bd_fs_vfat_wipe: + * @device: the device to wipe an vfat signature from + * @error: (out): place to store error (if any) + * + * Returns: whether an vfat signature was successfully wiped from the @device or + * not + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_vfat_wipe (const gchar *device, GError **error) { + return wipe_fs (device, "vfat", TRUE, error); +} + +/** + * bd_fs_vfat_check: + * @device: the device containing the file system to check + * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now + * passed to the 'fsck.vfat' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an vfat file system on the @device is clean or not + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_vfat_check (const gchar *device, const BDExtraArg **extra, GError **error) { + const gchar *args[4] = {"fsck.vfat", "-n", device, NULL}; + gint status = 0; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_FSCKVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + ret = bd_utils_exec_and_report_status_error (args, extra, &status, error); + if (!ret && (status == 1)) { + /* no error should be reported for exit code 1 -- Recoverable errors have been detected */ + g_clear_error (error); + } + return ret; +} + +/** + * bd_fs_vfat_repair: + * @device: the device containing the file system to repair + * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now + * passed to the 'fsck.vfat' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an vfat file system on the @device was successfully repaired + * (if needed) or not (error is set in that case) + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_vfat_repair (const gchar *device, const BDExtraArg **extra, GError **error) { + const gchar *args[4] = {"fsck.vfat", "-a", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_FSCKVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, extra, error); +} + +/** + * bd_fs_vfat_set_label: + * @device: the device containing the file system to set label for + * @label: label to set + * @error: (out): place to store error (if any) + * + * Returns: whether the label of vfat file system on the @device was + * successfully set or not + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError **error) { + const gchar *args[4] = {"fatlabel", device, label, NULL}; + + if (!check_deps (&avail_deps, DEPS_FATLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, NULL, error); +} + +/** + * bd_fs_vfat_get_info: + * @device: the device containing the file system to get info for + * @error: (out): place to store error (if any) + * + * Returns: (transfer full): information about the file system on @device or + * %NULL in case of error + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_QUERY + */ +BDFSVfatInfo* bd_fs_vfat_get_info (const gchar *device, GError **error) { + const gchar *args[4] = {"fsck.vfat", "-nv", device, NULL}; + blkid_probe probe = NULL; + gint fd = 0; + gint status = 0; + gboolean success = FALSE; + const gchar *value = NULL; + BDFSVfatInfo *ret = NULL; + gchar *output = NULL; + gchar **lines = NULL; + gchar **line_p = NULL; + gboolean have_cluster_size = FALSE; + gboolean have_cluster_count = FALSE; + guint64 full_cluster_count = 0; + guint64 cluster_count = 0; + gchar **key_val = NULL; + gint scanned = 0; + + if (!check_deps (&avail_deps, DEPS_FSCKVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return NULL; + + probe = blkid_new_probe (); + if (!probe) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + return NULL; + } + + fd = open (device, O_RDWR|O_CLOEXEC); + if (fd == -1) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + blkid_free_probe (probe); + return NULL; + } + + status = blkid_probe_set_device (probe, fd, 0, 0); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to create a probe for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } + + blkid_probe_enable_partitions(probe, 1); + + status = blkid_do_probe (probe); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to probe the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + return NULL; + } + + ret = g_new0 (BDFSVfatInfo, 1); + + status = blkid_probe_has_value (probe, "LABEL"); + + if (status == 0) + ret->label = g_strdup (""); + else { + status = blkid_probe_lookup_value (probe, "LABEL", &value, NULL); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get label for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_fs_vfat_info_free (ret); + return NULL; + } + + ret->label = g_strdup (value); + } + + status = blkid_probe_lookup_value (probe, "UUID", &value, NULL); + if (status != 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get label for the device '%s'", device); + blkid_free_probe (probe); + synced_close (fd); + bd_fs_vfat_info_free (ret); + return NULL; + } + + ret->uuid = g_strdup (value); + + blkid_free_probe (probe); + synced_close (fd); + + success = bd_utils_exec_and_capture_output (args, NULL, &output, error); + if (!success) { + /* error is already populated */ + bd_fs_vfat_info_free (ret); + return NULL; + } + + lines = g_strsplit (output, "\n", 0); + g_free (output); + for (line_p=lines; *line_p && (!have_cluster_size || !have_cluster_count); line_p++) { + if (!have_cluster_size && g_str_has_suffix (*line_p, "bytes per cluster")) { + ret->cluster_size = g_ascii_strtoull (*line_p, NULL, 0); + have_cluster_size = TRUE; + } else if (!have_cluster_count && g_str_has_prefix (*line_p, device)) { + key_val = g_strsplit (*line_p, ",", 2); + scanned = sscanf (key_val[1], " %" G_GUINT64_FORMAT "/" "%" G_GUINT64_FORMAT " clusters", + &full_cluster_count, &cluster_count); + if (scanned != 2) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get number of FAT clusters for '%s'", device); + bd_fs_vfat_info_free (ret); + g_strfreev (key_val); + g_strfreev (lines); + return NULL; + } + ret->cluster_count = cluster_count; + ret->free_cluster_count = cluster_count - full_cluster_count; + have_cluster_count = TRUE; + g_strfreev (key_val); + } + } + g_strfreev (lines); + + return ret; +} + +/** + * bd_fs_vfat_resize: + * @device: the device the file system of which to resize + * @new_size: new requested size for the file system (if 0, the file system is + * adapted to the underlying block device) + * @error: (out): place to store error (if any) + * + * Returns: whether the file system on @device was successfully resized or not + * + * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_vfat_resize (const gchar *device, guint64 new_size, GError **error) { + PedDevice *ped_dev = NULL; + PedGeometry geom = {0}; + PedGeometry new_geom = {0}; + PedFileSystem *fs = NULL; + PedSector start = 0; + PedSector length = 0; + gint status = 0; + guint64 progress_id = 0; + gchar *msg = NULL; + + msg = g_strdup_printf ("Started resizing vfat filesystem on the device '%s'", device); + progress_id = bd_utils_report_started (msg); + g_free (msg); + + ped_dev = ped_device_get (device); + if (!ped_dev) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get ped device for the device '%s'", device); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + status = ped_device_open (ped_dev); + if (status == 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to get open the device '%s'", device); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + status = ped_geometry_init (&geom, ped_dev, start, ped_dev->length); + if (status == 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to initialize geometry for the device '%s'", device); + ped_device_close (ped_dev); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + fs = ped_file_system_open(&geom); + if (!fs) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to read the filesystem on the device '%s'", device); + ped_device_close (ped_dev); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + if (new_size == 0) + length = ped_dev->length; + else + length = (PedSector) ((PedSector) new_size / ped_dev->sector_size); + + status = ped_geometry_init(&new_geom, ped_dev, start, length); + if (status == 0) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, + "Failed to initialize new geometry for the filesystem on '%s'", device); + ped_file_system_close (fs); + ped_device_close (ped_dev); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + status = ped_file_system_resize(fs, &new_geom, NULL); + if (status == 0) { + set_parted_error (error, BD_FS_ERROR_FAIL); + g_prefix_error (error, "Failed to resize the filesystem on '%s'", device); + ped_file_system_close (fs); + ped_device_close (ped_dev); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + + ped_file_system_close (fs); + ped_device_close (ped_dev); + bd_utils_report_finished (progress_id, "Completed"); + + return TRUE; + +} diff -Nru libblockdev-2.14/src/plugins/fs/vfat.h libblockdev-2.16/src/plugins/fs/vfat.h --- libblockdev-2.14/src/plugins/fs/vfat.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/vfat.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,26 @@ +#include +#include + +#ifndef BD_FS_VFAT +#define BD_FS_VFAT + +typedef struct BDFSVfatInfo { + gchar *label; + gchar *uuid; + guint64 cluster_size; + guint64 cluster_count; + guint64 free_cluster_count; +} BDFSVfatInfo; + +BDFSVfatInfo* bd_fs_vfat_info_copy (BDFSVfatInfo *data); +void bd_fs_vfat_info_free (BDFSVfatInfo *data); + +gboolean bd_fs_vfat_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_vfat_wipe (const gchar *device, GError **error); +gboolean bd_fs_vfat_check (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_vfat_repair (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError **error); +BDFSVfatInfo* bd_fs_vfat_get_info (const gchar *device, GError **error); +gboolean bd_fs_vfat_resize (const gchar *device, guint64 new_size, GError **error); + +#endif /* BD_FS_VFAT */ diff -Nru libblockdev-2.14/src/plugins/fs/xfs.c libblockdev-2.16/src/plugins/fs/xfs.c --- libblockdev-2.14/src/plugins/fs/xfs.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/xfs.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vratislav Podzimek + */ + +#include +#include +#include +#include + +#include "xfs.h" +#include "fs.h" +#include "common.h" + +static volatile guint avail_deps = 0; +static GMutex deps_check_lock; + +#define DEPS_MKFSXFS 0 +#define DEPS_MKFSXFS_MASK (1 << DEPS_MKFSXFS) +#define DEPS_XFS_DB 1 +#define DEPS_XFS_DB_MASK (1 << DEPS_XFS_DB) +#define DEPS_XFS_REPAIR 2 +#define DEPS_XFS_REPAIR_MASK (1 << DEPS_XFS_REPAIR) +#define DEPS_XFS_ADMIN 3 +#define DEPS_XFS_ADMIN_MASK (1 << DEPS_XFS_ADMIN) +#define DEPS_XFS_GROWFS 4 +#define DEPS_XFS_GROWFS_MASK (1 << DEPS_XFS_GROWFS) + +#define DEPS_LAST 5 + +static UtilDep deps[DEPS_LAST] = { + {"mkfs.xfs", NULL, NULL, NULL}, + {"xfs_db", NULL, NULL, NULL}, + {"xfs_repair", NULL, NULL, NULL}, + {"xfs_admin", NULL, NULL, NULL}, + {"xfs_growfs", NULL, NULL, NULL}, +}; + +static guint32 fs_mode_util[BD_FS_MODE_LAST+1] = { + /* mkfs wipe check repair set-label query resize */ + DEPS_MKFSXFS_MASK, 0, DEPS_XFS_DB_MASK, DEPS_XFS_REPAIR_MASK, DEPS_XFS_ADMIN_MASK, DEPS_XFS_ADMIN_MASK, DEPS_XFS_GROWFS_MASK +}; + +#define UNUSED __attribute__((unused)) + +/** + * bd_fs_xfs_is_tech_avail: + * @tech: the queried tech + * @mode: a bit mask of queried modes of operation (#BDFSTechMode) for @tech + * @error: (out): place to store error (details about why the @tech-@mode combination is not available) + * + * Returns: whether the @tech-@mode combination is available -- supported by the + * plugin implementation and having all the runtime dependencies available + */ +gboolean bd_fs_xfs_is_tech_avail (BDFSTech tech UNUSED, guint64 mode, GError **error) { + guint32 required = 0; + guint i = 0; + for (i = 0; i <= BD_FS_MODE_LAST; i++) + if (mode & (1 << i)) + required |= fs_mode_util[i]; + + return check_deps (&avail_deps, required, deps, DEPS_LAST, &deps_check_lock, error); +} + +/** + * bd_fs_xfs_info_copy: (skip) + * + * Creates a new copy of @data. + */ +BDFSXfsInfo* bd_fs_xfs_info_copy (BDFSXfsInfo *data) { + BDFSXfsInfo *ret = g_new0 (BDFSXfsInfo, 1); + + ret->label = g_strdup (data->label); + ret->uuid = g_strdup (data->uuid); + ret->block_size = data->block_size; + ret->block_count = data->block_count; + + return ret; +} + +/** + * bd_fs_xfs_info_free: (skip) + * + * Frees @data. + */ +void bd_fs_xfs_info_free (BDFSXfsInfo *data) { + g_free (data->label); + g_free (data->uuid); + g_free (data); +} + + +/** + * bd_fs_xfs_mkfs: + * @device: the device to create a new xfs fs on + * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now + * passed to the 'mkfs.xfs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether a new xfs fs was successfully created on @device or not + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_MKFS + */ +gboolean bd_fs_xfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { + const gchar *args[3] = {"mkfs.xfs", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_MKFSXFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, extra, error); +} + +/** + * bd_fs_xfs_wipe: + * @device: the device to wipe an xfs signature from + * @error: (out): place to store error (if any) + * + * Returns: whether an xfs signature was successfully wiped from the @device or + * not + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_WIPE + */ +gboolean bd_fs_xfs_wipe (const gchar *device, GError **error) { + return wipe_fs (device, "xfs", FALSE, error); +} + +/** + * bd_fs_xfs_check: + * @device: the device containing the file system to check + * @error: (out): place to store error (if any) + * + * Returns: whether an xfs file system on the @device is clean or not + * + * Note: if the file system is mounted it may be reported as unclean even if + * everything is okay and there are just some pending/in-progress writes + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_CHECK + */ +gboolean bd_fs_xfs_check (const gchar *device, GError **error) { + const gchar *args[6] = {"xfs_db", "-r", "-c", "check", device, NULL}; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_XFS_DB_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + ret = bd_utils_exec_and_report_error (args, NULL, error); + if (!ret && *error && g_error_matches ((*error), BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED)) + /* non-zero exit status -> the fs is not clean, but not an error */ + /* TODO: should we check that the device exists and contains an XFS FS beforehand? */ + g_clear_error (error); + return ret; +} + +/** + * bd_fs_xfs_repair: + * @device: the device containing the file system to repair + * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now + * passed to the 'xfs_repair' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether an xfs file system on the @device was successfully repaired + * (if needed) or not (error is set in that case) + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_REPAIR + */ +gboolean bd_fs_xfs_repair (const gchar *device, const BDExtraArg **extra, GError **error) { + const gchar *args[3] = {"xfs_repair", device, NULL}; + + if (!check_deps (&avail_deps, DEPS_XFS_REPAIR_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, extra, error); +} + +/** + * bd_fs_xfs_set_label: + * @device: the device containing the file system to set label for + * @label: label to set + * @error: (out): place to store error (if any) + * + * Returns: whether the label of xfs file system on the @device was + * successfully set or not + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_SET_LABEL + */ +gboolean bd_fs_xfs_set_label (const gchar *device, const gchar *label, GError **error) { + const gchar *args[5] = {"xfs_admin", "-L", label, device, NULL}; + if (!label || (strncmp (label, "", 1) == 0)) + args[2] = "--"; + + if (!check_deps (&avail_deps, DEPS_XFS_ADMIN_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + return bd_utils_exec_and_report_error (args, NULL, error); +} + +/** + * bd_fs_xfs_get_info: + * @device: the device containing the file system to get info for (device must + be mounted, trying to get info for an unmounted device will result + in an error) + * @error: (out): place to store error (if any) + * + * Returns: (transfer full): information about the file system on @device or + * %NULL in case of error + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_QUERY + */ +BDFSXfsInfo* bd_fs_xfs_get_info (const gchar *device, GError **error) { + const gchar *args[4] = {"xfs_admin", "-lu", device, NULL}; + gboolean success = FALSE; + gchar *output = NULL; + BDFSXfsInfo *ret = NULL; + gchar **lines = NULL; + gchar **line_p = NULL; + gboolean have_label = FALSE; + gboolean have_uuid = FALSE; + gchar *val_start = NULL; + gchar *val_end = NULL; + g_autofree gchar* mountpoint = NULL; + + if (!check_deps (&avail_deps, DEPS_XFS_ADMIN_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + mountpoint = bd_fs_get_mountpoint (device, error); + if (mountpoint == NULL) { + if (*error == NULL) { + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_MOUNTED, + "Can't get xfs file system information for '%s': Device is not mounted.", device); + return NULL; + } else { + g_prefix_error (error, "Error when trying to get mountpoint for '%s': ", device); + return NULL; + } + } + + success = bd_utils_exec_and_capture_output (args, NULL, &output, error); + if (!success) + /* error is already populated */ + return FALSE; + + ret = g_new0 (BDFSXfsInfo, 1); + lines = g_strsplit (output, "\n", 0); + g_free (output); + for (line_p=lines; line_p && *line_p && (!have_label || !have_uuid); line_p++) { + if (!have_label && g_str_has_prefix (*line_p, "label")) { + /* extract label from something like this: label = "TEST_LABEL" */ + val_start = strchr (*line_p, '"'); + if (val_start) + val_end = strchr(val_start + 1, '"'); + if (val_start && val_end) { + ret->label = g_strndup (val_start + 1, val_end - val_start - 1); + have_label = TRUE; + } + } else if (!have_uuid && g_str_has_prefix (*line_p, "UUID")) { + /* get right after the "UUID = " prefix */ + val_start = *line_p + 7; + ret->uuid = g_strdup (val_start); + have_uuid = TRUE; + } + } + g_strfreev (lines); + + args[0] = "xfs_info"; + args[1] = mountpoint; + args[2] = NULL; + success = bd_utils_exec_and_capture_output (args, NULL, &output, error); + if (!success) { + /* error is already populated */ + bd_fs_xfs_info_free (ret); + return FALSE; + } + + lines = g_strsplit (output, "\n", 0); + g_free (output); + line_p = lines; + /* find the beginning of the (data) section we are interested in */ + while (line_p && *line_p && !g_str_has_prefix (*line_p, "data")) + line_p++; + if (!line_p || !(*line_p)) { + /* error is already populated */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse xfs file system information"); + g_strfreev (lines); + bd_fs_xfs_info_free (ret); + return FALSE; + } + + /* extract data from something like this: "data = bsize=4096 blocks=262400, imaxpct=25" */ + val_start = strchr (*line_p, '='); + val_start++; + while (isspace (*val_start)) + val_start++; + if (g_str_has_prefix (val_start, "bsize")) { + val_start = strchr (val_start, '='); + val_start++; + ret->block_size = g_ascii_strtoull (val_start, NULL, 0); + } else { + /* error is already populated */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse xfs file system information"); + g_strfreev (lines); + bd_fs_xfs_info_free (ret); + return FALSE; + } + while (isdigit (*val_start) || isspace(*val_start)) + val_start++; + if (g_str_has_prefix (val_start, "blocks")) { + val_start = strchr (val_start, '='); + val_start++; + ret->block_count = g_ascii_strtoull (val_start, NULL, 0); + } else { + /* error is already populated */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse xfs file system information"); + g_strfreev (lines); + bd_fs_xfs_info_free (ret); + return FALSE; + } + g_strfreev (lines); + + return ret; +} + +/** + * bd_fs_xfs_resize: + * @mpoint: the mount point of the file system to resize + * @new_size: new requested size for the file system *in file system blocks* (see bd_fs_xfs_get_info()) + * (if 0, the file system is adapted to the underlying block device) + * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now + * passed to the 'xfs_growfs' utility) + * @error: (out): place to store error (if any) + * + * Returns: whether the file system mounted on @mpoint was successfully resized or not + * + * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_RESIZE + */ +gboolean bd_fs_xfs_resize (const gchar *mpoint, guint64 new_size, const BDExtraArg **extra, GError **error) { + const gchar *args[5] = {"xfs_growfs", NULL, NULL, NULL, NULL}; + gchar *size_str = NULL; + gboolean ret = FALSE; + + if (!check_deps (&avail_deps, DEPS_XFS_GROWFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + + if (new_size != 0) { + args[1] = "-D"; + /* xfs_growfs doesn't understand bytes, just a number of blocks */ + size_str = g_strdup_printf ("%"G_GUINT64_FORMAT, new_size); + args[2] = size_str; + args[3] = mpoint; + } else + args[1] = mpoint; + + ret = bd_utils_exec_and_report_error (args, extra, error); + + g_free (size_str); + return ret; +} diff -Nru libblockdev-2.14/src/plugins/fs/xfs.h libblockdev-2.16/src/plugins/fs/xfs.h --- libblockdev-2.14/src/plugins/fs/xfs.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs/xfs.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,25 @@ +#include +#include + +#ifndef BD_FS_XFS +#define BD_FS_XFS + +typedef struct BDFSXfsInfo { + gchar *label; + gchar *uuid; + guint64 block_size; + guint64 block_count; +} BDFSXfsInfo; + +BDFSXfsInfo* bd_fs_xfs_info_copy (BDFSXfsInfo *data); +void bd_fs_xfs_info_free (BDFSXfsInfo *data); + +gboolean bd_fs_xfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_xfs_wipe (const gchar *device, GError **error); +gboolean bd_fs_xfs_check (const gchar *device, GError **error); +gboolean bd_fs_xfs_repair (const gchar *device, const BDExtraArg **extra, GError **error); +gboolean bd_fs_xfs_set_label (const gchar *device, const gchar *label, GError **error); +BDFSXfsInfo* bd_fs_xfs_get_info (const gchar *device, GError **error); +gboolean bd_fs_xfs_resize (const gchar *mpoint, guint64 new_size, const BDExtraArg **extra, GError **error); + +#endif /* BD_FS_XFS */ diff -Nru libblockdev-2.14/src/plugins/fs.c libblockdev-2.16/src/plugins/fs.c --- libblockdev-2.14/src/plugins/fs.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs.c 2018-02-08 11:10:41.000000000 +0000 @@ -17,29 +17,13 @@ * Author: Vratislav Podzimek */ -#define _GNU_SOURCE -#include - #include -#include -#include -#include -#include +#include + #include -#include -#include -#include -#include -#include +#include #include "fs.h" -#include "check_deps.h" - -#define EXT2 "ext2" -#define EXT3 "ext3" -#define EXT4 "ext4" - -#define MOUNT_ERR_BUF_SIZE 1024 /** * SECTION: fs @@ -50,53 +34,10 @@ * A plugin for operations with file systems */ -typedef enum { - BD_FS_RESIZE, - BD_FS_REPAIR, - BD_FS_CHECK, - BD_FS_LABEL -} BDFsOpType; - -/** - * BDFSInfo: - * @type: filesystem identifier, must be present - * @check_util: required utility for consistency checking, "" if not needed and NULL for no support - * @repair_util: required utility for repair, "" if not needed and NULL for no support - * @resize_util: required utility for resize, "" if not needed and NULL for no support - * @resize_mode: resize availability flags, 0 if no support - */ -typedef struct BDFSInfo -{ - const gchar *type; - const gchar *check_util; - const gchar *repair_util; - const gchar *resize_util; - BDFsResizeFlags resize_mode; - const gchar *label_util; -} BDFSInfo; - -const BDFSInfo fs_info[] = { - {"xfs", "xfs_db", "xfs_repair", "xfs_growfs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW, "xfs_admin"}, - {"ext2", "e2fsck", "e2fsck", "resize2fs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "tune2fs"}, - {"ext3", "e2fsck", "e2fsck", "resize2fs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "tune2fs"}, - {"ext4", "e2fsck", "e2fsck", "resize2fs", BD_FS_ONLINE_GROW | BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "tune2fs"}, - {"vfat", "fsck.vfat", "fsck.vfat", "", BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "fatlabel"}, - {"ntfs", "ntfsfix", "ntfsfix", "ntfsresize", BD_FS_OFFLINE_GROW | BD_FS_OFFLINE_SHRINK, "ntfslabel"}, - {NULL, NULL, NULL, NULL, 0, NULL} -}; - -static const BDFSInfo * -get_fs_info (const gchar *type) -{ - g_return_val_if_fail (type != NULL, NULL); - - for (guint n = 0; fs_info[n].type != NULL; n++) { - if (strcmp (fs_info[n].type, type) == 0) - return &fs_info[n]; - } - - return NULL; -} +extern gboolean bd_fs_ext_is_tech_avail (BDFSTech tech, guint64 mode, GError **error); +extern gboolean bd_fs_xfs_is_tech_avail (BDFSTech tech, guint64 mode, GError **error); +extern gboolean bd_fs_vfat_is_tech_avail (BDFSTech tech, guint64 mode, GError **error); +extern gboolean bd_fs_ntfs_is_tech_avail (BDFSTech tech, guint64 mode, GError **error); /** * bd_fs_error_quark: (skip) @@ -107,243 +48,6 @@ } /** - * bd_fs_ext2_info_copy: (skip) - * - * Creates a new copy of @data. - */ -BDFSExt2Info* bd_fs_ext2_info_copy (BDFSExt2Info *data) { - BDFSExt2Info *ret = g_new0 (BDFSExt2Info, 1); - - ret->label = g_strdup (data->label); - ret->uuid = g_strdup (data->uuid); - ret->state = g_strdup (data->state); - ret->block_size = data->block_size; - ret->block_count = data->block_count; - ret->free_blocks = data->free_blocks; - - return ret; -} - -/** - * bd_fs_ext3_info_copy: (skip) - * - * Creates a new copy of @data. - */ -BDFSExt3Info* bd_fs_ext3_info_copy (BDFSExt3Info *data) { - return (BDFSExt3Info*) bd_fs_ext2_info_copy (data); -} - -/** - * bd_fs_ext4_info_copy: (skip) - * - * Creates a new copy of @data. - */ -BDFSExt4Info* bd_fs_ext4_info_copy (BDFSExt4Info *data) { - return (BDFSExt4Info*) bd_fs_ext2_info_copy (data); -} - -/** - * bd_fs_ext2_info_free: (skip) - * - * Frees @data. - */ -void bd_fs_ext2_info_free (BDFSExt2Info *data) { - g_free (data->label); - g_free (data->uuid); - g_free (data->state); - g_free (data); -} - -/** - * bd_fs_ext3_info_free: (skip) - * - * Frees @data. - */ -void bd_fs_ext3_info_free (BDFSExt3Info *data) { - bd_fs_ext2_info_free ((BDFSExt2Info*) data); -} - -/** - * bd_fs_ext4_info_free: (skip) - * - * Frees @data. - */ -void bd_fs_ext4_info_free (BDFSExt4Info *data) { - bd_fs_ext2_info_free ((BDFSExt2Info*) data); -} - -/** - * bd_fs_xfs_info_copy: (skip) - * - * Creates a new copy of @data. - */ -BDFSXfsInfo* bd_fs_xfs_info_copy (BDFSXfsInfo *data) { - BDFSXfsInfo *ret = g_new0 (BDFSXfsInfo, 1); - - ret->label = g_strdup (data->label); - ret->uuid = g_strdup (data->uuid); - ret->block_size = data->block_size; - ret->block_count = data->block_count; - - return ret; -} - -/** - * bd_fs_xfs_info_free: (skip) - * - * Frees @data. - */ -void bd_fs_xfs_info_free (BDFSXfsInfo *data) { - g_free (data->label); - g_free (data->uuid); - g_free (data); -} - -/** - * bd_fs_vfat_info_copy: (skip) - * - * Creates a new copy of @data. - */ -BDFSVfatInfo* bd_fs_vfat_info_copy (BDFSVfatInfo *data) { - BDFSVfatInfo *ret = g_new0 (BDFSVfatInfo, 1); - - ret->label = g_strdup (data->label); - ret->uuid = g_strdup (data->uuid); - ret->cluster_size = data->cluster_size; - ret->cluster_count = data->cluster_count; - ret->free_cluster_count = data->free_cluster_count; - - return ret; -} - -/** - * bd_fs_vfat_info_free: (skip) - * - * Frees @data. - */ -void bd_fs_vfat_info_free (BDFSVfatInfo *data) { - g_free (data->label); - g_free (data->uuid); - g_free (data); -} - -/** - * bd_fs_ntfs_info_copy: (skip) - * - * Creates a new copy of @data. - */ -BDFSNtfsInfo* bd_fs_ntfs_info_copy (BDFSNtfsInfo *data) { - BDFSNtfsInfo *ret = g_new0 (BDFSNtfsInfo, 1); - - ret->size = data->size; - ret->free_space = data->free_space; - - return ret; -} - -/** - * bd_fs_ntfs_info_free: (skip) - * - * Frees @data. - */ -void bd_fs_ntfs_info_free (BDFSNtfsInfo *data) { - g_free (data); -} - -typedef struct MountArgs { - const gchar *mountpoint; - const gchar *device; - const gchar *fstype; - const gchar *options; - const gchar *spec; - gboolean lazy; - gboolean force; -} MountArgs; - -typedef gboolean (*MountFunc) (MountArgs *args, GError **error); - -static gboolean do_mount (MountArgs *args, GError **error); - -static volatile guint avail_deps = 0; -static GMutex deps_check_lock; - -#define DEPS_MKE2FS 0 -#define DEPS_MKE2FS_MASK (1 << DEPS_MKE2FS) -#define DEPS_E2FSCK 1 -#define DEPS_E2FSCK_MASK (1 << DEPS_E2FSCK) -#define DEPS_TUNE2FS 2 -#define DEPS_TUNE2FS_MASK (1 << DEPS_TUNE2FS) -#define DEPS_DUMPE2FS 3 -#define DEPS_DUMPE2FS_MASK (1 << DEPS_DUMPE2FS) -#define DEPS_RESIZE2FS 4 -#define DEPS_RESIZE2FS_MASK (1 << DEPS_RESIZE2FS) - -#define DEPS_MKFSXFS 5 -#define DEPS_MKFSXFS_MASK (1 << DEPS_MKFSXFS) -#define DEPS_XFS_DB 6 -#define DEPS_XFS_DB_MASK (1 << DEPS_XFS_DB) -#define DEPS_XFS_REPAIR 7 -#define DEPS_XFS_REPAIR_MASK (1 << DEPS_XFS_REPAIR) -#define DEPS_XFS_ADMIN 8 -#define DEPS_XFS_ADMIN_MASK (1 << DEPS_XFS_ADMIN) -#define DEPS_XFS_GROWFS 9 -#define DEPS_XFS_GROWFS_MASK (1 << DEPS_XFS_GROWFS) - -#define DEPS_MKFSVFAT 10 -#define DEPS_MKFSVFAT_MASK (1 << DEPS_MKFSVFAT) -#define DEPS_FATLABEL 11 -#define DEPS_FATLABEL_MASK (1 << DEPS_FATLABEL) -#define DEPS_FSCKVFAT 12 -#define DEPS_FSCKVFAT_MASK (1 << DEPS_FSCKVFAT) - -#define DEPS_MKNTFS 13 -#define DEPS_MKNTFS_MASK (1 << DEPS_MKNTFS) -#define DEPS_NTFSFIX 14 -#define DEPS_NTFSFIX_MASK (1 << DEPS_NTFSFIX) -#define DEPS_NTFSRESIZE 15 -#define DEPS_NTFSRESIZE_MASK (1 << DEPS_NTFSRESIZE) -#define DEPS_NTFSLABEL 16 -#define DEPS_NTFSLABEL_MASK (1 << DEPS_NTFSLABEL) -#define DEPS_NTFSCLUSTER 17 -#define DEPS_NTFSCLUSTER_MASK (1 << DEPS_NTFSCLUSTER) - -#define DEPS_LAST 18 - -static UtilDep deps[DEPS_LAST] = { - {"mke2fs", NULL, NULL, NULL}, - {"e2fsck", NULL, NULL, NULL}, - {"tune2fs", NULL, NULL, NULL}, - {"dumpe2fs", NULL, NULL, NULL}, - {"resize2fs", NULL, NULL, NULL}, - - {"mkfs.xfs", NULL, NULL, NULL}, - {"xfs_db", NULL, NULL, NULL}, - {"xfs_repair", NULL, NULL, NULL}, - {"xfs_admin", NULL, NULL, NULL}, - {"xfs_growfs", NULL, NULL, NULL}, - - {"mkfs.vfat", NULL, NULL, NULL}, - {"fatlabel", NULL, NULL, NULL}, - {"fsck.vfat", NULL, NULL, NULL}, - - {"mkntfs", NULL, NULL, NULL}, - {"ntfsfix", NULL, NULL, NULL}, - {"ntfsresize", NULL, NULL, NULL}, - {"ntfslabel", NULL, NULL, NULL}, - {"ntfscluster", NULL, NULL, NULL}, -}; - -static guint32 fs_mode_util[][FS_MODE_LAST+1] = { - /* mkfs wipe check repair set-label query resize */ -/* ext2 */ {DEPS_MKE2FS_MASK, 0, DEPS_E2FSCK_MASK, DEPS_E2FSCK_MASK, DEPS_TUNE2FS_MASK, DEPS_DUMPE2FS_MASK, DEPS_RESIZE2FS_MASK}, -/* ext3 */ {DEPS_MKE2FS_MASK, 0, DEPS_E2FSCK_MASK, DEPS_E2FSCK_MASK, DEPS_TUNE2FS_MASK, DEPS_DUMPE2FS_MASK, DEPS_RESIZE2FS_MASK}, -/* ext4 */ {DEPS_MKE2FS_MASK, 0, DEPS_E2FSCK_MASK, DEPS_E2FSCK_MASK, DEPS_TUNE2FS_MASK, DEPS_DUMPE2FS_MASK, DEPS_RESIZE2FS_MASK}, -/* xfs */ {DEPS_MKFSXFS_MASK, 0, DEPS_XFS_DB_MASK, DEPS_XFS_REPAIR_MASK, DEPS_XFS_ADMIN_MASK, DEPS_XFS_ADMIN_MASK, DEPS_XFS_GROWFS_MASK}, -/* vfat */ {DEPS_MKFSVFAT_MASK, 0, DEPS_FSCKVFAT_MASK, DEPS_FSCKVFAT_MASK, DEPS_FATLABEL_MASK, DEPS_FSCKVFAT_MASK, 0}, -/* ntfs */ {DEPS_MKNTFS_MASK, 0, DEPS_NTFSFIX_MASK, DEPS_NTFSFIX_MASK, DEPS_NTFSLABEL_MASK, DEPS_NTFSCLUSTER_MASK, DEPS_NTFSRESIZE_MASK} -}; - -/** * bd_fs_check_deps: * * Returns: whether the plugin's runtime dependencies are satisfied or not @@ -352,7 +56,33 @@ * */ gboolean bd_fs_check_deps () { - return TRUE; + gboolean ret = TRUE; + guint i = 0; + GError *error = NULL; + + for (i = BD_FS_TECH_EXT2; i <= BD_FS_TECH_EXT4; i++) { + ret = ret && bd_fs_ext_is_tech_avail (i, 0xffffffff, &error); + if (!ret && error) { + g_warning ("%s", error->message); + g_clear_error (&error); + } + } + ret = ret && bd_fs_xfs_is_tech_avail (BD_FS_TECH_XFS, 0xffffffff, &error); + if (!ret && error) { + g_warning ("%s", error->message); + g_clear_error (&error); + } + ret = ret && bd_fs_vfat_is_tech_avail (BD_FS_TECH_VFAT, 0xffffffff, &error); + if (!ret && error) { + g_warning ("%s", error->message); + g_clear_error (&error); + } + ret = ret && bd_fs_ntfs_is_tech_avail (BD_FS_TECH_NTFS, 0xffffffff, &error); + if (!ret && error) { + g_warning ("%s", error->message); + g_clear_error (&error); + } + return ret; } /** @@ -388,2857 +118,31 @@ * plugin implementation and having all the runtime dependencies available */ gboolean bd_fs_is_tech_avail (BDFSTech tech, guint64 mode, GError **error) { - guint32 required = 0; - gint fs = 0; - guint i = 0; - if (tech == BD_FS_TECH_GENERIC || tech == BD_FS_TECH_MOUNT) /* @mode is ignored, there are no special modes for GENERIC and MOUNT technologies */ /* generic features and mounting are supported by this plugin without any dependencies */ return TRUE; - if (tech > LAST_FS) { + if (tech > BD_FS_LAST_FS) { g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_TECH_UNAVAIL, "Unknown technology"); return FALSE; } - fs = tech - FS_OFFSET; - for (i = 0; i <= FS_MODE_LAST; i++) - if (mode & (1 << i)) - required |= fs_mode_util[fs][i]; - - return check_deps (&avail_deps, required, deps, DEPS_LAST, &deps_check_lock, error); -} - - -/** - * set_parted_error: (skip) - * - * Set error from the parted error stored in 'error_msg'. In case there is none, - * the error is set up with an empty string. Otherwise it is set up with the - * parted's error message and is a subject to later g_prefix_error() call. - * - * Returns: whether there was some message from parted or not - */ -static gboolean set_parted_error (GError **error, BDFsError type) { - gchar *error_msg = NULL; - error_msg = bd_get_error_msg (); - if (error_msg) { - g_set_error (error, BD_FS_ERROR, type, - " (%s)", error_msg); - g_free (error_msg); - error_msg = NULL; - return TRUE; - } else { - g_set_error_literal (error, BD_FS_ERROR, type, ""); - return FALSE; - } -} - -static gint synced_close (gint fd) { - gint ret = 0; - ret = fsync (fd); - if (close (fd) != 0) - ret = 1; - return ret; -} - -#ifndef LIBMOUNT_NEW_ERR_API -static void parse_unmount_error_old (struct libmnt_context *cxt, int rc, const gchar *spec, GError **error) { - int syscall_errno = 0; - - if (mnt_context_syscall_called (cxt)) { - syscall_errno = mnt_context_get_syscall_errno (cxt); - switch (syscall_errno) { - case EBUSY: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Target busy."); - break; - case EINVAL: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Not a mount point."); - break; - case EPERM: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, - "Operation not permitted."); - break; - default: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Unmount syscall failed: %d.", syscall_errno); - break; - } - } else { - if (rc == -EPERM) { - if (mnt_context_tab_applied (cxt)) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, - "Operation not permitted."); - else - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Not mounted."); - } else { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to unmount %s.", spec); - } - } - return; -} -#else -static void parse_unmount_error_new (struct libmnt_context *cxt, int rc, const gchar *spec, GError **error) { - int ret = 0; - int syscall_errno = 0; - char buf[MOUNT_ERR_BUF_SIZE] = {0}; - gboolean permission = FALSE; - - ret = mnt_context_get_excode (cxt, rc, buf, MOUNT_ERR_BUF_SIZE - 1); - if (ret != 0) { - /* check whether the call failed because of lack of permission */ - if (mnt_context_syscall_called (cxt)) { - syscall_errno = mnt_context_get_syscall_errno (cxt); - permission = syscall_errno == EPERM; - } else - permission = ret == MNT_EX_USAGE && mnt_context_tab_applied (cxt); - - if (permission) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, - "Operation not permitted."); - else { - if (*buf == '\0') - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Unknow error when unmounting %s", spec); - else - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "%s", buf); - } - } else - /* mnt_context_umount returned non-zero, but mnt_context_get_excode - * returned zero -- this should never happen, but just in case set error - * to something sane here - */ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Unknow error when unmounting %s", spec); - return; -} -#endif - -static gboolean do_unmount (MountArgs *args, GError **error) { - struct libmnt_context *cxt = NULL; - int ret = 0; - - cxt = mnt_new_context (); - - if (mnt_context_set_target (cxt, args->spec) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set '%s' as target for umount", args->spec); - mnt_free_context(cxt); - return FALSE; - } - - if (args->lazy) { - if (mnt_context_enable_lazy (cxt, TRUE) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set lazy unmount for '%s'", args->spec); - mnt_free_context(cxt); - return FALSE; - } - } - - if (args->force) { - if (mnt_context_enable_force (cxt, TRUE) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set force unmount for '%s'", args->spec); - mnt_free_context(cxt); - return FALSE; - } - } - - ret = mnt_context_umount (cxt); - if (ret != 0) { -#ifdef LIBMOUNT_NEW_ERR_API - parse_unmount_error_new (cxt, ret, args->spec, error); -#else - parse_unmount_error_old (cxt, ret, args->spec, error); -#endif - mnt_free_context(cxt); - return FALSE; - } - - mnt_free_context(cxt); - return TRUE; -} - -#ifndef LIBMOUNT_NEW_ERR_API -static gboolean parse_mount_error_old (struct libmnt_context *cxt, int rc, MountArgs *args, GError **error) { - int syscall_errno = 0; - unsigned long mflags = 0; - - if (mnt_context_get_mflags (cxt, &mflags) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get options from string '%s'.", args->options); - return FALSE; - } - - if (mnt_context_syscall_called (cxt) == 1) { - syscall_errno = mnt_context_get_syscall_errno (cxt); - switch (syscall_errno) { - case EBUSY: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Source is already mounted or target is busy."); - break; - case EINVAL: - if (mflags & MS_REMOUNT) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Remount attempted, but %s is not mounted at %s.", args->device, args->mountpoint); - else if (mflags & MS_MOVE) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Move attempted, but %s is not a mount point.", args->device); - else - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Wrong fs type, %s has an invalid superblock or missing helper program.", args->device); - break; - case EPERM: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, - "Operation not permitted."); - break; - case ENOTBLK: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "%s is not a block device.", args->device); - break; - case ENOTDIR: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "%s is not a directory.", args->mountpoint); - break; - case ENODEV: - if (args->fstype == NULL || strlen (args->fstype) == 0) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Filesystem type not specified"); - else - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Filesystem type %s not configured in kernel.", args->fstype); - break; - case EROFS: - case EACCES: - if (mflags & MS_RDONLY) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Cannot mount %s read-only.", args->device); - break; - } else if (args->options && (mnt_optstr_get_option (args->options, "rw", NULL, NULL) == 0)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "%s is write-protected but `rw' option given.", args->device); - break; - } else if (mflags & MS_BIND) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Mount %s on %s failed.", args->device, args->mountpoint); - break; - } - /* new versions of libmount do this automatically */ - else { - MountArgs ro_args; - gboolean success = FALSE; - - ro_args.device = args->device; - ro_args.mountpoint = args->mountpoint; - ro_args.fstype = args->fstype; - if (!args->options) - ro_args.options = g_strdup ("ro"); - else - ro_args.options = g_strdup_printf ("%s,ro", args->options); - - success = do_mount (&ro_args, error); - - g_free ((gchar*) ro_args.options); - - return success; - } - default: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Mount syscall failed: %d.", syscall_errno); - break; - } - } else { - switch (rc) { - case -EPERM: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, - "Only root can mount %s.", args->device); - break; - case -EBUSY: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "%s is already mounted.", args->device); - break; - /* source or target explicitly defined and not found in fstab */ - case -MNT_ERR_NOFSTAB: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Can't find %s in %s.", args->device ? args->device : args->mountpoint, mnt_get_fstab_path ()); - break; - case -MNT_ERR_MOUNTOPT: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to parse mount options"); - break; - case -MNT_ERR_NOSOURCE: - if (args->device) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Can't find %s.", args->device); - else - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Mount source not defined."); - break; - case -MNT_ERR_LOOPDEV: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to setup loop device"); - break; - case -MNT_ERR_NOFSTYPE: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Filesystem type not specified"); - break; - default: - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to mount %s.", args->device ? args->device : args->mountpoint); - break; - } - } - - return FALSE; -} - -#else -static void parse_mount_error_new (struct libmnt_context *cxt, int rc, MountArgs *args, GError **error) { - int ret = 0; - int syscall_errno = 0; - char buf[MOUNT_ERR_BUF_SIZE] = {0}; - gboolean permission = FALSE; - - ret = mnt_context_get_excode (cxt, rc, buf, MOUNT_ERR_BUF_SIZE - 1); - if (ret != 0) { - /* check whether the call failed because of lack of permission */ - if (mnt_context_syscall_called (cxt)) { - syscall_errno = mnt_context_get_syscall_errno (cxt); - permission = syscall_errno == EPERM; - } else - permission = ret == MNT_EX_USAGE && mnt_context_tab_applied (cxt); - - if (permission) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_AUTH, - "Operation not permitted."); - else { - if (*buf == '\0') - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Unknow error when mounting %s", args->device ? args->device : args->mountpoint); - else - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "%s", buf); - } - } - - return; -} -#endif - -static gboolean do_mount (MountArgs *args, GError **error) { - struct libmnt_context *cxt = NULL; - int ret = 0; - gboolean success = FALSE; - - cxt = mnt_new_context (); - - if (!args->mountpoint && !args->device) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "You must specify at least one of: mount point, device."); - mnt_free_context(cxt); - return FALSE; - } - - if (args->mountpoint) { - if (mnt_context_set_target (cxt, args->mountpoint) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set '%s' as target for mount", args->mountpoint); - mnt_free_context(cxt); - return FALSE; - } - } - - if (args->device) { - if (mnt_context_set_source (cxt, args->device) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set '%s' as source for mount", args->device); - mnt_free_context(cxt); - return FALSE; - } - } - - if (args->fstype) { - if (mnt_context_set_fstype (cxt, args->fstype) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set '%s' as fstype for mount", args->fstype); - mnt_free_context(cxt); - return FALSE; - } - } - - if (args->options) { - if (mnt_context_set_options (cxt, args->options) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set '%s' as options for mount", args->options); - mnt_free_context(cxt); + switch (tech) { + case BD_FS_TECH_EXT2: + case BD_FS_TECH_EXT3: + case BD_FS_TECH_EXT4: + return bd_fs_ext_is_tech_avail (tech, mode, error); + case BD_FS_TECH_XFS: + return bd_fs_xfs_is_tech_avail (tech, mode, error); + case BD_FS_TECH_VFAT: + return bd_fs_vfat_is_tech_avail (tech, mode, error); + case BD_FS_TECH_NTFS: + return bd_fs_ntfs_is_tech_avail (tech, mode, error); + default: + /* this should never be reached (see the comparison with LAST_FS + above), but better safe than sorry */ + g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_TECH_UNAVAIL, "Unknown technology"); return FALSE; - } } - -#ifdef LIBMOUNT_NEW_ERR_API - /* we don't want libmount to try RDONLY mounts if we were explicitly given the "rw" option */ - if (args->options && (mnt_optstr_get_option (args->options, "rw", NULL, NULL) == 0)) - mnt_context_enable_rwonly_mount (cxt, TRUE); -#endif - - ret = mnt_context_mount (cxt); - - if (ret != 0) { -#ifdef LIBMOUNT_NEW_ERR_API - parse_mount_error_new (cxt, ret, args, error); - success = FALSE; -#else - success = parse_mount_error_old (cxt, ret, args, error); -#endif - } else - success = TRUE; - - mnt_free_context(cxt); - return success; -} - -static gboolean set_uid (uid_t uid, GError **error) { - if (setresuid (uid, -1, -1) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error setting uid: %m"); - return FALSE; - } - - return TRUE; -} - -static gboolean set_gid (gid_t gid, GError **error) { - if (setresgid (gid, -1, -1) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error setting gid: %m"); - return FALSE; - } - - return TRUE; -} - -static gboolean run_as_user (MountFunc func, MountArgs *args, uid_t run_as_uid, gid_t run_as_gid, GError ** error) { - uid_t current_uid = -1; - gid_t current_gid = -1; - pid_t pid = -1; - pid_t wpid = -1; - int pipefd[2]; - int status = 0; - GIOChannel *channel = NULL; - GError *local_error = NULL; - gchar *error_msg = NULL; - gsize msglen = 0; - - current_uid = getuid (); - current_gid = getgid (); - - if (pipe(pipefd) == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error creating pipe."); - return FALSE; - } - - pid = fork (); - - if (pid == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error forking."); - return FALSE; - } else if (pid == 0) { - close (pipefd[0]); - - if (run_as_gid != current_gid) { - if (!set_gid (run_as_gid, error)) { - if (write(pipefd[1], (*error)->message, strlen((*error)->message)) < 0) - _exit (BD_FS_ERROR_PIPE); - else - _exit ((*error)->code); - } - } - - if (run_as_uid != current_uid) { - if (!set_uid (run_as_uid, error)) { - if (write(pipefd[1], (*error)->message, strlen((*error)->message)) < 0) - _exit (BD_FS_ERROR_PIPE); - else - _exit ((*error)->code); - } - } - - if (!func (args, error)) { - if (write(pipefd[1], (*error)->message, strlen((*error)->message)) < 0) - _exit (BD_FS_ERROR_PIPE); - else - _exit ((*error)->code); - } - - _exit (EXIT_SUCCESS); - - } else { - close (pipefd[1]); - - do { - wpid = waitpid (pid, &status, WUNTRACED | WCONTINUED); - if (wpid == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error while waiting for process."); - return FALSE; - } - - if (WIFEXITED (status)) { - if (WEXITSTATUS (status) != EXIT_SUCCESS) { - if (WEXITSTATUS (status) == BD_FS_ERROR_PIPE) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error while reading error."); - return FALSE; - } - - channel = g_io_channel_unix_new (pipefd[0]); - if (g_io_channel_read_to_end (channel, &error_msg, &msglen, &local_error) != G_IO_STATUS_NORMAL) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error while reading error: %s (%d)", - local_error->message, local_error->code); - g_clear_error (&local_error); - g_io_channel_unref (channel); - return FALSE; - } - - if (g_io_channel_shutdown (channel, TRUE, &local_error) == G_IO_STATUS_ERROR) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Error shutting down GIO channel: %s (%d)", - local_error->message, local_error->code); - g_clear_error (&local_error); - g_io_channel_unref (channel); - return FALSE; - } - - if (WEXITSTATUS (status) > BD_FS_ERROR_AUTH) - g_set_error_literal (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - error_msg); - else - g_set_error_literal (error, BD_FS_ERROR, WEXITSTATUS (status), - error_msg); - - g_io_channel_unref (channel); - return FALSE; - } else - return TRUE; - } else if (WIFSIGNALED (status)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Killed by signal %d.", WTERMSIG(status)); - return FALSE; - } - - } while (!WIFEXITED (status) && !WIFSIGNALED (status)); - } - - return FALSE; -} - -/** - * bd_fs_unmount: - * @spec: mount point or device to unmount - * @lazy: enable/disable lazy unmount - * @force: enable/disable force unmount - * @extra: (allow-none) (array zero-terminated=1): extra options for the unmount - * currently only 'run_as_uid' - * and 'run_as_gid' are supported - * value must be a valid non zero - * uid (gid) - * @error: (out): place to store error (if any) - * - * Returns: whether @spec was successfully unmounted or not - * - * Tech category: %BD_FS_TECH_GENERIC (no mode, ignored) - */ -gboolean bd_fs_unmount (const gchar *spec, gboolean lazy, gboolean force, const BDExtraArg **extra, GError **error) { - uid_t run_as_uid = -1; - gid_t run_as_gid = -1; - uid_t current_uid = -1; - gid_t current_gid = -1; - const BDExtraArg **extra_p = NULL; - MountArgs args; - - args.spec = spec; - args.lazy = lazy; - args.force = force; - - current_uid = getuid (); - run_as_uid = current_uid; - - current_gid = getgid (); - run_as_gid = current_gid; - - if (extra) { - for (extra_p=extra; *extra_p; extra_p++) { - if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_uid") == 0)) { - run_as_uid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); - - /* g_ascii_strtoull returns 0 in case of error */ - if (run_as_uid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Invalid specification of UID: '%s'", (*extra_p)->val); - return FALSE; - } - } else if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_gid") == 0)) { - run_as_gid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); - - /* g_ascii_strtoull returns 0 in case of error */ - if (run_as_gid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Invalid specification of GID: '%s'", (*extra_p)->val); - return FALSE; - } - } else { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Unsupported argument for unmount: '%s'", (*extra_p)->opt); - return FALSE; - } - } - } - - if (run_as_uid != current_uid || run_as_gid != current_gid) { - return run_as_user ((MountFunc) do_unmount, &args, run_as_uid, run_as_gid, error); - } else - return do_unmount (&args, error); - - return TRUE; -} - -/** - * bd_fs_mount: - * @device: (allow-none): device to mount, if not specified @mountpoint entry - * from fstab will be used - * @mountpoint: (allow-none): mountpoint for @device, if not specified @device - * entry from fstab will be used - * @fstype: (allow-none): filesystem type - * @options: (allow-none): comma delimited options for mount - * @extra: (allow-none) (array zero-terminated=1): extra options for the mount - * currently only 'run_as_uid' - * and 'run_as_gid' are supported - * value must be a valid non zero - * uid (gid) - * @error: (out): place to store error (if any) - * - * Returns: whether @device (or @mountpoint) was successfully mounted or not - * - * Tech category: %BD_FS_TECH_MOUNT (no mode, ignored) - */ -gboolean bd_fs_mount (const gchar *device, const gchar *mountpoint, const gchar *fstype, const gchar *options, const BDExtraArg **extra, GError **error) { - uid_t run_as_uid = -1; - gid_t run_as_gid = -1; - uid_t current_uid = -1; - gid_t current_gid = -1; - const BDExtraArg **extra_p = NULL; - MountArgs args; - - args.device = device; - args.mountpoint = mountpoint; - args.fstype = fstype; - args.options = options; - - current_uid = getuid (); - run_as_uid = current_uid; - - current_gid = getgid (); - run_as_gid = current_gid; - - if (extra) { - for (extra_p=extra; *extra_p; extra_p++) { - if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_uid") == 0)) { - run_as_uid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); - - /* g_ascii_strtoull returns 0 in case of error */ - if (run_as_uid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Invalid specification of UID: '%s'", (*extra_p)->val); - return FALSE; - } - } else if ((*extra_p)->opt && (g_strcmp0 ((*extra_p)->opt, "run_as_gid") == 0)) { - run_as_gid = g_ascii_strtoull ((*extra_p)->val, NULL, 0); - - /* g_ascii_strtoull returns 0 in case of error */ - if (run_as_gid == 0 && (g_strcmp0 ((*extra_p)->opt, "0") != 0)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Invalid specification of GID: '%s'", (*extra_p)->val); - return FALSE; - } - } else { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Unsupported argument for unmount: '%s'", (*extra_p)->opt); - return FALSE; - } - } - } - - if (run_as_uid != current_uid || run_as_gid != current_gid) { - return run_as_user ((MountFunc) do_mount, &args, run_as_uid, run_as_gid, error); - } else - return do_mount (&args, error); - - return TRUE; -} - -/** - * bd_fs_get_mountpoint: - * @device: device to find mountpoint for - * @error: (out): place to store error (if any) - * - * Get mountpoint for @device. If @device is mounted multiple times only - * one mountpoint will be returned. - * - * Returns: (transfer full): mountpoint for @device, %NULL in case device is - * not mounted or in case of an error (@error is set - * in this case) - * - * Tech category: %BD_FS_TECH_MOUNT (no mode, ignored) - */ -gchar* bd_fs_get_mountpoint (const gchar *device, GError **error) { - struct libmnt_table *table = NULL; - struct libmnt_fs *fs = NULL; - struct libmnt_cache *cache = NULL; - gint ret = 0; - gchar *mountpoint = NULL; - const gchar *target = NULL; - - table = mnt_new_table (); - cache = mnt_new_cache (); - - ret = mnt_table_set_cache (table, cache); - if (ret != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to set cache for mount info table."); - mnt_free_table (table); - return NULL; - } - - ret = mnt_table_parse_mtab (table, NULL); - if (ret != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to parse mount info."); - mnt_free_table (table); - mnt_free_cache (cache); - return NULL; - } - - fs = mnt_table_find_source (table, device, MNT_ITER_FORWARD); - if (!fs) { - mnt_free_table (table); - mnt_free_cache (cache); - return NULL; - } - - target = mnt_fs_get_target (fs); - if (!target) { - mnt_free_fs (fs); - mnt_free_table (table); - mnt_free_cache (cache); - return NULL; - } - - mountpoint = g_strdup (target); - mnt_free_fs (fs); - mnt_free_table (table); - mnt_free_cache (cache); - return mountpoint; -} - -/** - * bd_fs_wipe: - * @device: the device to wipe signatures from - * @all: whether to wipe all (%TRUE) signatures or just the first (%FALSE) one - * @error: (out): place to store error (if any) - * - * Returns: whether signatures were successfully wiped on @device or not - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_wipe (const gchar *device, gboolean all, GError **error) { - blkid_probe probe = NULL; - gint fd = 0; - gint status = 0; - guint64 progress_id = 0; - gchar *msg = NULL; - guint n_try = 0; - - msg = g_strdup_printf ("Started wiping signatures from the device '%s'", device); - progress_id = bd_utils_report_started (msg); - g_free (msg); - - probe = blkid_new_probe (); - if (!probe) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a new probe"); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - fd = open (device, O_RDWR|O_CLOEXEC); - if (fd == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to open the device '%s'", device); - blkid_free_probe (probe); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - /* we may need to try mutliple times with some delays in case the device is - busy at the very moment */ - for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { - status = blkid_probe_set_device (probe, fd, 0, 0); - if (status != 0) - g_usleep (100 * 1000); /* microseconds */ - } - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - blkid_probe_enable_partitions(probe, 1); - blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC); - blkid_probe_enable_superblocks(probe, 1); - blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); - - /* we may need to try mutliple times with some delays in case the device is - busy at the very moment */ - for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { - status = blkid_do_safeprobe (probe); - if (status == 1) - break; - if (status < 0) - g_usleep (100 * 1000); /* microseconds */ - } - if (status == 1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOFS, - "No signature detected on the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - blkid_reset_probe (probe); - status = blkid_do_probe (probe); - - if (status < 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to probe the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - status = blkid_do_wipe (probe, FALSE); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to wipe signatures on the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - while (all && (blkid_do_probe (probe) == 0)) { - status = blkid_do_wipe (probe, FALSE); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to wipe signatures on the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - } - - blkid_free_probe (probe); - synced_close (fd); - - bd_utils_report_finished (progress_id, "Completed"); - - return TRUE; -} - -/** - * bd_fs_clean: - * @device: the device to clean - * @error: (out): place to store error (if any) - * - * Clean all signatures from @device. - * Difference between this and bd_fs_wipe() is that this function doesn't - * return error if @device is already empty. This will also always remove - * all signatures from @device, not only the first one. - * - * Returns: whether @device was successfully cleaned or not - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_clean (const gchar *device, GError **error) { - gboolean ret = FALSE; - - ret = bd_fs_wipe (device, TRUE, error); - - if (!ret) { - if (g_error_matches (*error, BD_FS_ERROR, BD_FS_ERROR_NOFS)) { - /* ignore 'empty device' error */ - g_clear_error (error); - return TRUE; - } else { - g_prefix_error (error, "Failed to clean %s:", device); - return FALSE; - } - } else - return TRUE; -} - -/** - * bd_fs_get_fstype: - * @device: the device to probe - * @error: (out): place to store error (if any) - * - * Get first signature on @device as a string. - * - * Returns: (transfer full): type of filesystem found on @device, %NULL in case - * no signature has been detected or in case of error - * (@error is set in this case) - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY - */ -gchar* bd_fs_get_fstype (const gchar *device, GError **error) { - blkid_probe probe = NULL; - gint fd = 0; - gint status = 0; - const gchar *value = NULL; - gchar *fstype = NULL; - size_t len = 0; - guint n_try = 0; - - probe = blkid_new_probe (); - if (!probe) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a new probe"); - return FALSE; - } - - fd = open (device, O_RDWR|O_CLOEXEC); - if (fd == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to open the device '%s'", device); - blkid_free_probe (probe); - return FALSE; - } - - /* we may need to try mutliple times with some delays in case the device is - busy at the very moment */ - for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { - status = blkid_probe_set_device (probe, fd, 0, 0); - if (status != 0) - g_usleep (100 * 1000); /* microseconds */ - } - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return FALSE; - } - - blkid_probe_enable_partitions (probe, 1); - blkid_probe_set_partitions_flags (probe, BLKID_PARTS_MAGIC); - blkid_probe_enable_superblocks (probe, 1); - blkid_probe_set_superblocks_flags (probe, BLKID_SUBLKS_USAGE | BLKID_SUBLKS_TYPE | - BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); - - /* we may need to try mutliple times with some delays in case the device is - busy at the very moment */ - for (n_try=5, status=-1; !(status == 0 || status == 1) && (n_try > 0); n_try--) { - status = blkid_do_safeprobe (probe); - if (status < 0) - g_usleep (100 * 1000); /* microseconds */ - } - if (status < 0) { - /* -1 or -2 = error during probing*/ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to probe the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return NULL; - } else if (status == 1) { - /* 1 = nothing detected */ - blkid_free_probe (probe); - synced_close (fd); - return NULL; - } - - status = blkid_probe_lookup_value (probe, "USAGE", &value, &len); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get usage for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return NULL; - } - - if (strncmp (value, "filesystem", 10) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_INVAL, - "The signature on the device '%s' is of type '%s', not 'filesystem'", device, value); - blkid_free_probe (probe); - synced_close (fd); - return NULL; - } - - status = blkid_probe_lookup_value (probe, "TYPE", &value, &len); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get filesystem type for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return NULL; - } - - fstype = g_strdup (value); - blkid_free_probe (probe); - synced_close (fd); - - return fstype; -} - -static gboolean has_fs (blkid_probe probe, const gchar *device, const gchar *fs_type, GError **error) { - gint status = 0; - const gchar *value = NULL; - size_t len = 0; - - status = blkid_do_safeprobe (probe); - if (status != 0) { - if (status < 0) - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to probe the device '%s'", device); - return FALSE; - } - - if (fs_type) { - status = blkid_probe_lookup_value (probe, "TYPE", &value, &len); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get filesystem type for the device '%s'", device); - return FALSE; - } - - if (strncmp (value, fs_type, len-1) != 0) { - return FALSE; - } - } - - blkid_reset_probe (probe); - return TRUE; -} - -static gboolean wipe_fs (const gchar *device, const gchar *fs_type, gboolean wipe_all, GError **error) { - blkid_probe probe = NULL; - gint fd = 0; - gint status = 0; - const gchar *value = NULL; - size_t len = 0; - guint64 progress_id = 0; - gchar *msg = NULL; - gboolean has_fs_type = TRUE; - guint n_try = 0; - - msg = g_strdup_printf ("Started wiping '%s' signatures from the device '%s'", fs_type, device); - progress_id = bd_utils_report_started (msg); - g_free (msg); - - probe = blkid_new_probe (); - if (!probe) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - fd = open (device, O_RDWR|O_CLOEXEC); - if (fd == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - blkid_free_probe (probe); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { - status = blkid_probe_set_device (probe, fd, 0, 0); - if (status != 0) - g_usleep (100 * 1000); /* microseconds */ - } - status = blkid_probe_set_device (probe, fd, 0, 0); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - blkid_probe_enable_partitions(probe, 1); - blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC); - blkid_probe_enable_superblocks(probe, 1); - blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_USAGE | BLKID_SUBLKS_TYPE | - BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); - - for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) { - status = blkid_do_probe (probe); - if (status != 0) - g_usleep (100 * 1000); /* microseconds */ - } - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to probe the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - status = blkid_probe_lookup_value (probe, "USAGE", &value, NULL); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get signature type for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - if (strncmp (value, "filesystem", 10) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_INVAL, - "The signature on the device '%s' is of type '%s', not 'filesystem'", device, value); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - if (fs_type) { - status = blkid_probe_lookup_value (probe, "TYPE", &value, &len); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get filesystem type for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - if (strncmp (value, fs_type, len-1) != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_INVAL, - "The file system type on the device '%s' is '%s', not '%s'", device, value, fs_type); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - } - - status = blkid_do_wipe (probe, FALSE); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to wipe the filesystem signature on the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - blkid_reset_probe (probe); - - if (wipe_all) { - has_fs_type = has_fs (probe, device, fs_type, error); - - while (has_fs_type) { - status = blkid_do_probe (probe); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to probe the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - status = blkid_do_wipe (probe, FALSE); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to wipe the filesystem signature on the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - blkid_reset_probe (probe); - has_fs_type = has_fs (probe, device, fs_type, error); - - } - } - - blkid_free_probe (probe); - synced_close (fd); - - bd_utils_report_finished (progress_id, "Completed"); - - return TRUE; -} - -static gboolean ext_mkfs (const gchar *device, const BDExtraArg **extra, const gchar *ext_version, GError **error) { - const gchar *args[6] = {"mke2fs", "-t", ext_version, "-F", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_MKE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * xfs_resize_device: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system *in bytes* - * (if 0, the file system is adapted to the underlying block device) - * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now - * passed to the 'xfs_growfs' utility) - * @error: (out): place to store error (if any) - * - * This is just a helper function for bd_fs_resize. - * - * Returns: whether the file system on @device was successfully resized or not - */ - -static gboolean xfs_resize_device (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { - g_autofree gchar* mountpoint = NULL; - gboolean ret = FALSE; - gboolean success = FALSE; - gboolean unmount = FALSE; - GError *local_error = NULL; - BDFSXfsInfo* xfs_info = NULL; - - mountpoint = bd_fs_get_mountpoint (device, error); - if (!mountpoint) { - if (*error == NULL) { - /* device is not mounted -- we need to mount it */ - mountpoint = g_build_path (G_DIR_SEPARATOR_S, g_get_tmp_dir (), "blockdev.XXXXXX", NULL); - mountpoint = g_mkdtemp (mountpoint); - if (!mountpoint) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create temporary directory for mounting '%s' " - "before resizing it.", device); - return FALSE; - } - ret = bd_fs_mount (device, mountpoint, "xfs", NULL, NULL, error); - if (!ret) { - g_prefix_error (error, "Failed to mount '%s' before resizing it: ", device); - return FALSE; - } else - unmount = TRUE; - } else { - g_prefix_error (error, "Error when trying to get mountpoint for '%s': ", device); - return FALSE; - } - } - - xfs_info = bd_fs_xfs_get_info (device, error); - if (!xfs_info) { - return FALSE; - } - - new_size = (new_size + xfs_info->block_size - 1) / xfs_info->block_size; - bd_fs_xfs_info_free (xfs_info); - - success = bd_fs_xfs_resize (mountpoint, new_size, extra, error); - - if (unmount) { - ret = bd_fs_unmount (mountpoint, FALSE, FALSE, NULL, &local_error); - if (!ret) { - if (success) { - /* resize was successful but unmount failed */ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_UNMOUNT_FAIL, - "Failed to unmount '%s' after resizing it: %s", - device, local_error->message); - g_clear_error (&local_error); - return FALSE; - } else - /* both resize and unmount were unsuccessful but the error - from the resize is more important so just ignore the - unmount error */ - g_clear_error (&local_error); - } - } - - return success; -} - -static gboolean device_operation (const gchar *device, BDFsOpType op, guint64 new_size, const gchar *label, GError **error) { - const gchar* op_name = NULL; - g_autofree gchar* fstype = NULL; - - fstype = bd_fs_get_fstype (device, error); - if (!fstype) { - if (*error == NULL) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOFS, - "No filesystem detected on the device '%s'", device); - return FALSE; - } else { - g_prefix_error (error, "Error when trying to detect filesystem on '%s': ", device); - return FALSE; - } - } - - if (g_strcmp0 (fstype, "ext2") == 0 || g_strcmp0 (fstype, "ext3") == 0 - || g_strcmp0 (fstype, "ext4") == 0) { - switch (op) { - case BD_FS_RESIZE: - return bd_fs_ext4_resize (device, new_size, NULL, error); - case BD_FS_REPAIR: - return bd_fs_ext4_repair (device, TRUE, NULL, error); - case BD_FS_CHECK: - return bd_fs_ext4_check (device, NULL, error); - case BD_FS_LABEL: - return bd_fs_ext4_set_label (device, label, error); - } - } else if (g_strcmp0 (fstype, "xfs") == 0) { - switch (op) { - case BD_FS_RESIZE: - return xfs_resize_device (device, new_size, NULL, error); - case BD_FS_REPAIR: - return bd_fs_xfs_repair (device, NULL, error); - case BD_FS_CHECK: - return bd_fs_xfs_check (device, error); - case BD_FS_LABEL: - return bd_fs_xfs_set_label (device, label, error); - } - } else if (g_strcmp0 (fstype, "vfat") == 0) { - switch (op) { - case BD_FS_RESIZE: - return bd_fs_vfat_resize (device, new_size, error); - case BD_FS_REPAIR: - return bd_fs_vfat_repair (device, NULL, error); - case BD_FS_CHECK: - return bd_fs_vfat_check (device, NULL, error); - case BD_FS_LABEL: - return bd_fs_vfat_set_label (device, label, error); - } - } else if (g_strcmp0 (fstype, "ntfs") == 0) { - switch (op) { - case BD_FS_RESIZE: - return bd_fs_ntfs_resize (device, new_size, error); - case BD_FS_REPAIR: - return bd_fs_ntfs_repair (device, error); - case BD_FS_CHECK: - return bd_fs_ntfs_check (device, error); - case BD_FS_LABEL: - return bd_fs_ntfs_set_label (device, label, error); - } - } - switch (op) { - case BD_FS_RESIZE: - op_name = "Resizing"; - break; - case BD_FS_REPAIR: - op_name = "Repairing"; - break; - case BD_FS_CHECK: - op_name = "Checking"; - break; - case BD_FS_LABEL: - op_name = "Setting the label of"; - break; - } - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_SUPPORTED, - "%s filesystem '%s' is not supported.", op_name, fstype); - return FALSE; -} - -/** - * bd_fs_resize: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system (if 0, the file system is - * adapted to the underlying block device) - * @error: (out): place to store error (if any) - * - * Resize filesystem on @device. This calls other fs resize functions from this - * plugin based on detected filesystem (e.g. bd_fs_xfs_resize for XFS). This - * function will return an error for unknown/unsupported filesystems. - * - * Returns: whether the file system on @device was successfully resized or not - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_resize (const gchar *device, guint64 new_size, GError **error) { - return device_operation (device, BD_FS_RESIZE, new_size, NULL, error); -} - -/** - * bd_fs_repair: - * @device: the device the file system of which to repair - * @error: (out): place to store error (if any) - * - * Repair filesystem on @device. This calls other fs repair functions from this - * plugin based on detected filesystem (e.g. bd_fs_xfs_repair for XFS). This - * function will return an error for unknown/unsupported filesystems. - * - * Returns: whether the file system on @device was successfully repaired or not - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_repair (const gchar *device, GError **error) { - return device_operation (device, BD_FS_REPAIR, 0, NULL, error); - } - -/** - * bd_fs_check: - * @device: the device the file system of which to check - * @error: (out): place to store error (if any) - * - * Check filesystem on @device. This calls other fs check functions from this - * plugin based on detected filesystem (e.g. bd_fs_xfs_check for XFS). This - * function will return an error for unknown/unsupported filesystems. - * - * Returns: whether the file system on @device passed the consistency check or not - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_check (const gchar *device, GError **error) { - return device_operation (device, BD_FS_CHECK, 0, NULL, error); -} - -/** - * bd_fs_set_label: - * @device: the device with file system to set the label for - * @error: (out): place to store error (if any) - * - * Set label for filesystem on @device. This calls other fs label functions from this - * plugin based on detected filesystem (e.g. bd_fs_xfs_set_label for XFS). This - * function will return an error for unknown/unsupported filesystems. - * - * Returns: whether the file system on @device was successfully relabled or not - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_set_label (const gchar *device, const gchar *label, GError **error) { - return device_operation (device, BD_FS_LABEL, 0, label, error); - } - -static gboolean query_fs_operation (const gchar *fs_type, BDFsOpType op, gchar **required_utility, BDFsResizeFlags *mode, GError **error) { - gboolean ret; - const BDFSInfo *fsinfo = NULL; - const gchar* op_name = NULL; - const gchar* exec_util = NULL; - - if (required_utility != NULL) - *required_utility = NULL; - - if (mode != NULL) - *mode = 0; - - fsinfo = get_fs_info (fs_type); - if (fsinfo != NULL) { - switch (op) { - case BD_FS_RESIZE: - op_name = "Resizing"; - exec_util = fsinfo->resize_util; - break; - case BD_FS_REPAIR: - op_name = "Repairing"; - exec_util = fsinfo->repair_util; - break; - case BD_FS_CHECK: - op_name = "Checking"; - exec_util = fsinfo->check_util; - break; - case BD_FS_LABEL: - op_name = "Setting the label of"; - exec_util = fsinfo->label_util; - break; - } - } - - if (fsinfo == NULL || exec_util == NULL) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_SUPPORTED, - "%s filesystem '%s' is not supported.", op_name, fs_type); - return FALSE; - } - - if (mode != NULL) - *mode = fsinfo->resize_mode; - - if (strlen(exec_util) == 0) { /* empty string if no util needed */ - return TRUE; - } - - ret = bd_utils_check_util_version (exec_util, NULL, "", NULL, NULL); - if (!ret && required_utility != NULL) - *required_utility = g_strdup (exec_util); - - return ret; -} - -/** - * bd_fs_can_resize: - * @type: the filesystem type to be tested for installed resize support - * @mode: (out): flags for allowed resizing (i.e. growing/shrinking support for online/offline) - * @required_utility: (out) (transfer full): the utility binary which is required for resizing (if missing i.e. returns FALSE but no error) - * @error: (out): place to store error (if any) - * - * Searches for the required utility to resize the given filesystem and returns whether - * it is installed. The mode flags indicate if growing and/or shrinking resize is available if - * mounted/unmounted. - * Unknown filesystems or filesystems which do not support resizing result in errors. - * - * Returns: whether filesystem resize is available - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY - */ -gboolean bd_fs_can_resize (const gchar *type, BDFsResizeFlags *mode, gchar **required_utility, GError **error) { - return query_fs_operation (type, BD_FS_RESIZE, required_utility, mode, error); -} - -/** - * bd_fs_can_check: - * @type: the filesystem type to be tested for installed consistency check support - * @required_utility: (out) (transfer full): the utility binary which is required for checking (if missing i.e. returns FALSE but no error) - * @error: (out): place to store error (if any) - * - * Searches for the required utility to check the given filesystem and returns whether - * it is installed. - * Unknown filesystems or filesystems which do not support checking result in errors. - * - * Returns: whether filesystem check is available - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY - */ -gboolean bd_fs_can_check (const gchar *type, gchar **required_utility, GError **error) { - return query_fs_operation (type, BD_FS_CHECK, required_utility, NULL, error); -} - -/** - * bd_fs_can_repair: - * @type: the filesystem type to be tested for installed repair support - * @required_utility: (out) (transfer full): the utility binary which is required for repairing (if missing i.e. return FALSE but no error) - * @error: (out): place to store error (if any) - * - * Searches for the required utility to repair the given filesystem and returns whether - * it is installed. - * Unknown filesystems or filesystems which do not support reparing result in errors. - * - * Returns: whether filesystem repair is available - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY - */ -gboolean bd_fs_can_repair (const gchar *type, gchar **required_utility, GError **error) { - return query_fs_operation (type, BD_FS_REPAIR, required_utility, NULL, error); -} - -/** - * bd_fs_can_set_label: - * @type: the filesystem type to be tested for installed label support - * @required_utility: (out) (transfer full): the utility binary which is required for relabeling (if missing i.e. return FALSE but no error) - * @error: (out): place to store error (if any) - * - * Searches for the required utility to set the label of the given filesystem and returns whether - * it is installed. - * Unknown filesystems or filesystems which do not support setting the label result in errors. - * - * Returns: whether setting filesystem label is available - * - * Tech category: %BD_FS_TECH_GENERIC-%BD_FS_TECH_MODE_QUERY - */ -gboolean bd_fs_can_set_label (const gchar *type, gchar **required_utility, GError **error) { - return query_fs_operation (type, BD_FS_LABEL, required_utility, NULL, error); -} - -/** - * bd_fs_ext2_mkfs: - * @device: the device to create a new ext2 fs on - * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now - * passed to the 'mke2fs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether a new ext2 fs was successfully created on @device or not - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_MKFS - */ -gboolean bd_fs_ext2_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { - return ext_mkfs (device, extra, EXT2, error); -} - -/** - * bd_fs_ext3_mkfs: - * @device: the device to create a new ext3 fs on - * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now - * passed to the 'mke2fs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether a new ext3 fs was successfully created on @device or not - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_MKFS - */ -gboolean bd_fs_ext3_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { - return ext_mkfs (device, extra, EXT3, error); -} - -/** - * bd_fs_ext4_mkfs: - * @device: the device to create a new ext4 fs on - * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now - * passed to the 'mkfs.ext4' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether a new ext4 fs was successfully created on @device or not - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_MKFS - */ -gboolean bd_fs_ext4_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { - return ext_mkfs (device, extra, EXT4, error); -} - -/** - * bd_fs_ext2_wipe: - * @device: the device to wipe an ext2 signature from - * @error: (out): place to store error (if any) - * - * Returns: whether an ext2 signature was successfully wiped from the @device or - * not - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_ext2_wipe (const gchar *device, GError **error) { - return wipe_fs (device, EXT2, FALSE, error); -} - -/** - * bd_fs_ext3_wipe: - * @device: the device to wipe an ext3 signature from - * @error: (out): place to store error (if any) - * - * Returns: whether an ext3 signature was successfully wiped from the @device or - * not - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_ext3_wipe (const gchar *device, GError **error) { - return wipe_fs (device, EXT3, FALSE, error); -} - -/** - * bd_fs_ext4_wipe: - * @device: the device to wipe an ext4 signature from - * @error: (out): place to store error (if any) - * - * Returns: whether an ext4 signature was successfully wiped from the @device or - * not - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_ext4_wipe (const gchar *device, GError **error) { - return wipe_fs (device, EXT4, FALSE, error); -} - -static gboolean ext_check (const gchar *device, const BDExtraArg **extra, GError **error) { - /* Force checking even if the file system seems clean. AND - * Open the filesystem read-only, and assume an answer of no to all - * questions. */ - const gchar *args[5] = {"e2fsck", "-f", "-n", device, NULL}; - gint status = 0; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_E2FSCK_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - ret = bd_utils_exec_and_report_status_error (args, extra, &status, error); - if (!ret && (status == 4)) { - /* no error should be reported for exit code 4 - File system errors left uncorrected */ - g_clear_error (error); - } - return ret; -} - -/** - * bd_fs_ext2_check: - * @device: the device the file system on which to check - * @extra: (allow-none) (array zero-terminated=1): extra options for the check (right now - * passed to the 'e2fsck' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an ext2 file system on the @device is clean or not - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_ext2_check (const gchar *device, const BDExtraArg **extra, GError **error) { - return ext_check (device, extra, error); -} - -/** - * bd_fs_ext3_check: - * @device: the device the file system on which to check - * @extra: (allow-none) (array zero-terminated=1): extra options for the check (right now - * passed to the 'e2fsck' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an ext3 file system on the @device is clean or not - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_ext3_check (const gchar *device, const BDExtraArg **extra, GError **error) { - return ext_check (device, extra, error); -} - -/** - * bd_fs_ext4_check: - * @device: the device the file system on which to check - * @extra: (allow-none) (array zero-terminated=1): extra options for the check (right now - * passed to the 'e2fsck' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an ext4 file system on the @device is clean or not - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_ext4_check (const gchar *device, const BDExtraArg **extra, GError **error) { - return ext_check (device, extra, error); -} - -static gboolean ext_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { - /* Force checking even if the file system seems clean. AND - * Automatically repair what can be safely repaired. OR - * Assume an answer of `yes' to all questions. */ - const gchar *args[5] = {"e2fsck", "-f", unsafe ? "-y" : "-p", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_E2FSCK_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * bd_fs_ext2_repair: - * @device: the device the file system on which to repair - * @unsafe: whether to do unsafe operations too - * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now - * passed to the 'e2fsck' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an ext2 file system on the @device was successfully repaired - * (if needed) or not (error is set in that case) - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_ext2_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { - return ext_repair (device, unsafe, extra, error); -} - -/** - * bd_fs_ext3_repair: - * @device: the device the file system on which to repair - * @unsafe: whether to do unsafe operations too - * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now - * passed to the 'e2fsck' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an ext3 file system on the @device was successfully repaired - * (if needed) or not (error is set in that case) - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_ext3_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { - return ext_repair (device, unsafe, extra, error); -} - -/** - * bd_fs_ext4_repair: - * @device: the device the file system on which to repair - * @unsafe: whether to do unsafe operations too - * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now - * passed to the 'e2fsck' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an ext4 file system on the @device was successfully repaired - * (if needed) or not (error is set in that case) - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_ext4_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error) { - return ext_repair (device, unsafe, extra, error); -} - -static gboolean ext_set_label (const gchar *device, const gchar *label, GError **error) { - const gchar *args[5] = {"tune2fs", "-L", label, device, NULL}; - - if (!check_deps (&avail_deps, DEPS_TUNE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, NULL, error); -} - -/** - * bd_fs_ext2_set_label: - * @device: the device the file system on which to set label for - * @label: label to set - * @error: (out): place to store error (if any) - * - * Returns: whether the label of ext2 file system on the @device was - * successfully set or not - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_ext2_set_label (const gchar *device, const gchar *label, GError **error) { - return ext_set_label (device, label, error); -} - -/** - * bd_fs_ext3_set_label: - * @device: the device the file system on which to set label for - * @label: label to set - * @error: (out): place to store error (if any) - * - * Returns: whether the label of ext3 file system on the @device was - * successfully set or not - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_ext3_set_label (const gchar *device, const gchar *label, GError **error) { - return ext_set_label (device, label, error); -} - -/** - * bd_fs_ext4_set_label: - * @device: the device the file system on which to set label for - * @label: label to set - * @error: (out): place to store error (if any) - * - * Returns: whether the label of ext4 file system on the @device was - * successfully set or not - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_ext4_set_label (const gchar *device, const gchar *label, GError **error) { - return ext_set_label (device, label, error); -} - -/** - * parse_output_vars: (skip) - * @str: string to parse - * @item_sep: item separator(s) (key-value pairs separator) - * @key_val_sep: key-value separator(s) (typically ":" or "=") - * @num_items: (out): number of parsed items (key-value pairs) - * - * Returns: (transfer full): GHashTable containing the key-value pairs parsed - * from the @str. - */ -static GHashTable* parse_output_vars (const gchar *str, const gchar *item_sep, const gchar *key_val_sep, guint *num_items) { - GHashTable *table = NULL; - gchar **items = NULL; - gchar **item_p = NULL; - gchar **key_val = NULL; - - table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - *num_items = 0; - - items = g_strsplit_set (str, item_sep, 0); - for (item_p=items; *item_p; item_p++) { - key_val = g_strsplit (*item_p, key_val_sep, 2); - if (g_strv_length (key_val) == 2) { - /* we only want to process valid lines (with the separator) */ - g_hash_table_insert (table, g_strstrip (key_val[0]), g_strstrip (key_val[1])); - (*num_items)++; - } else - /* invalid line, just free key_val */ - g_strfreev (key_val); - } - - g_strfreev (items); - return table; -} - -static BDFSExtInfo* get_ext_info_from_table (GHashTable *table, gboolean free_table) { - BDFSExtInfo *ret = g_new0 (BDFSExtInfo, 1); - gchar *value = NULL; - - ret->label = g_strdup ((gchar*) g_hash_table_lookup (table, "Filesystem volume name")); - if ((!ret->label) || (g_strcmp0 (ret->label, "") == 0)) - ret->label = g_strdup (""); - ret->uuid = g_strdup ((gchar*) g_hash_table_lookup (table, "Filesystem UUID")); - ret->state = g_strdup ((gchar*) g_hash_table_lookup (table, "Filesystem state")); - - value = (gchar*) g_hash_table_lookup (table, "Block size"); - if (value) - ret->block_size = g_ascii_strtoull (value, NULL, 0); - else - ret->block_size = 0; - value = (gchar*) g_hash_table_lookup (table, "Block count"); - if (value) - ret->block_count = g_ascii_strtoull (value, NULL, 0); - else - ret->block_count = 0; - value = (gchar*) g_hash_table_lookup (table, "Free blocks"); - if (value) - ret->free_blocks = g_ascii_strtoull (value, NULL, 0); - else - ret->free_blocks = 0; - - if (free_table) - g_hash_table_destroy (table); - - return ret; -} - -static BDFSExtInfo* ext_get_info (const gchar *device, GError **error) { - const gchar *args[4] = {"dumpe2fs", "-h", device, NULL}; - gboolean success = FALSE; - gchar *output = NULL; - GHashTable *table = NULL; - guint num_items = 0; - BDFSExtInfo *ret = NULL; - - if (!check_deps (&avail_deps, DEPS_DUMPE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - success = bd_utils_exec_and_capture_output (args, NULL, &output, error); - if (!success) { - /* error is already populated */ - return FALSE; - } - - table = parse_output_vars (output, "\n", ":", &num_items); - g_free (output); - if (!table || (num_items == 0)) { - /* something bad happened or some expected items were missing */ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse ext4 file system information"); - if (table) - g_hash_table_destroy (table); - return NULL; - } - - ret = get_ext_info_from_table (table, TRUE); - if (!ret) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse ext4 file system information"); - return NULL; - } - - return ret; -} - -/** - * bd_fs_ext2_get_info: - * @device: the device the file system of which to get info for - * @error: (out): place to store error (if any) - * - * Returns: (transfer full): information about the file system on @device or - * %NULL in case of error - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_QUERY - */ -BDFSExt2Info* bd_fs_ext2_get_info (const gchar *device, GError **error) { - return (BDFSExt2Info*) ext_get_info (device, error); -} - -/** - * bd_fs_ext3_get_info: - * @device: the device the file system of which to get info for - * @error: (out): place to store error (if any) - * - * Returns: (transfer full): information about the file system on @device or - * %NULL in case of error - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_QUERY - */ -BDFSExt3Info* bd_fs_ext3_get_info (const gchar *device, GError **error) { - return (BDFSExt3Info*) ext_get_info (device, error); -} - -/** - * bd_fs_ext4_get_info: - * @device: the device the file system of which to get info for - * @error: (out): place to store error (if any) - * - * Returns: (transfer full): information about the file system on @device or - * %NULL in case of error - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_QUERY - */ -BDFSExt4Info* bd_fs_ext4_get_info (const gchar *device, GError **error) { - return (BDFSExt4Info*) ext_get_info (device, error); -} - -static gboolean ext_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { - const gchar *args[4] = {"resize2fs", device, NULL, NULL}; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_RESIZE2FS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - if (new_size != 0) - /* resize2fs doesn't understand bytes, just 512B sectors */ - args[2] = g_strdup_printf ("%"G_GUINT64_FORMAT"s", new_size / 512); - ret = bd_utils_exec_and_report_error (args, extra, error); - - g_free ((gchar *) args[2]); - return ret; -} - -/** - * bd_fs_ext2_resize: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system (if 0, the file system is - * adapted to the underlying block device) - * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now - * passed to the 'resize2fs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether the file system on @device was successfully resized or not - * - * Tech category: %BD_FS_TECH_EXT2-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_ext2_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { - return ext_resize (device, new_size, extra, error); -} - -/** - * bd_fs_ext3_resize: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system (if 0, the file system is - * adapted to the underlying block device) - * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now - * passed to the 'resize2fs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether the file system on @device was successfully resized or not - * - * Tech category: %BD_FS_TECH_EXT3-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_ext3_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { - return ext_resize (device, new_size, extra, error); -} - -/** - * bd_fs_ext4_resize: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system (if 0, the file system is - * adapted to the underlying block device) - * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now - * passed to the 'resize2fs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether the file system on @device was successfully resized or not - * - * Tech category: %BD_FS_TECH_EXT4-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_ext4_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error) { - return ext_resize (device, new_size, extra, error); -} - -/** - * bd_fs_xfs_mkfs: - * @device: the device to create a new xfs fs on - * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now - * passed to the 'mkfs.xfs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether a new xfs fs was successfully created on @device or not - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_MKFS - */ -gboolean bd_fs_xfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { - const gchar *args[3] = {"mkfs.xfs", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_MKFSXFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * bd_fs_xfs_wipe: - * @device: the device to wipe an xfs signature from - * @error: (out): place to store error (if any) - * - * Returns: whether an xfs signature was successfully wiped from the @device or - * not - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_xfs_wipe (const gchar *device, GError **error) { - return wipe_fs (device, "xfs", FALSE, error); -} - -/** - * bd_fs_xfs_check: - * @device: the device containing the file system to check - * @error: (out): place to store error (if any) - * - * Returns: whether an xfs file system on the @device is clean or not - * - * Note: if the file system is mounted it may be reported as unclean even if - * everything is okay and there are just some pending/in-progress writes - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_xfs_check (const gchar *device, GError **error) { - const gchar *args[6] = {"xfs_db", "-r", "-c", "check", device, NULL}; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_XFS_DB_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - ret = bd_utils_exec_and_report_error (args, NULL, error); - if (!ret && *error && g_error_matches ((*error), BD_UTILS_EXEC_ERROR, BD_UTILS_EXEC_ERROR_FAILED)) - /* non-zero exit status -> the fs is not clean, but not an error */ - /* TODO: should we check that the device exists and contains an XFS FS beforehand? */ - g_clear_error (error); - return ret; -} - -/** - * bd_fs_xfs_repair: - * @device: the device containing the file system to repair - * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now - * passed to the 'xfs_repair' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an xfs file system on the @device was successfully repaired - * (if needed) or not (error is set in that case) - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_xfs_repair (const gchar *device, const BDExtraArg **extra, GError **error) { - const gchar *args[3] = {"xfs_repair", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_XFS_REPAIR_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * bd_fs_xfs_set_label: - * @device: the device containing the file system to set label for - * @label: label to set - * @error: (out): place to store error (if any) - * - * Returns: whether the label of xfs file system on the @device was - * successfully set or not - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_xfs_set_label (const gchar *device, const gchar *label, GError **error) { - const gchar *args[5] = {"xfs_admin", "-L", label, device, NULL}; - if (!label || (strncmp (label, "", 1) == 0)) - args[2] = "--"; - - if (!check_deps (&avail_deps, DEPS_XFS_ADMIN_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, NULL, error); -} - -/** - * bd_fs_xfs_get_info: - * @device: the device containing the file system to get info for (device must - be mounted, trying to get info for an unmounted device will result - in an error) - * @error: (out): place to store error (if any) - * - * Returns: (transfer full): information about the file system on @device or - * %NULL in case of error - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_QUERY - */ -BDFSXfsInfo* bd_fs_xfs_get_info (const gchar *device, GError **error) { - const gchar *args[4] = {"xfs_admin", "-lu", device, NULL}; - gboolean success = FALSE; - gchar *output = NULL; - BDFSXfsInfo *ret = NULL; - gchar **lines = NULL; - gchar **line_p = NULL; - gboolean have_label = FALSE; - gboolean have_uuid = FALSE; - gchar *val_start = NULL; - gchar *val_end = NULL; - g_autofree gchar* mountpoint = NULL; - - if (!check_deps (&avail_deps, DEPS_XFS_ADMIN_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - mountpoint = bd_fs_get_mountpoint (device, error); - if (mountpoint == NULL) { - if (*error == NULL) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_MOUNTED, - "Can't get xfs file system information for '%s': Device is not mounted.", device); - return NULL; - } else { - g_prefix_error (error, "Error when trying to get mountpoint for '%s': ", device); - return NULL; - } - } - - success = bd_utils_exec_and_capture_output (args, NULL, &output, error); - if (!success) - /* error is already populated */ - return FALSE; - - ret = g_new0 (BDFSXfsInfo, 1); - lines = g_strsplit (output, "\n", 0); - g_free (output); - for (line_p=lines; line_p && *line_p && (!have_label || !have_uuid); line_p++) { - if (!have_label && g_str_has_prefix (*line_p, "label")) { - /* extract label from something like this: label = "TEST_LABEL" */ - val_start = strchr (*line_p, '"'); - if (val_start) - val_end = strchr(val_start + 1, '"'); - if (val_start && val_end) { - ret->label = g_strndup (val_start + 1, val_end - val_start - 1); - have_label = TRUE; - } - } else if (!have_uuid && g_str_has_prefix (*line_p, "UUID")) { - /* get right after the "UUID = " prefix */ - val_start = *line_p + 7; - ret->uuid = g_strdup (val_start); - have_uuid = TRUE; - } - } - g_strfreev (lines); - - args[0] = "xfs_info"; - args[1] = mountpoint; - args[2] = NULL; - success = bd_utils_exec_and_capture_output (args, NULL, &output, error); - if (!success) { - /* error is already populated */ - bd_fs_xfs_info_free (ret); - return FALSE; - } - - lines = g_strsplit (output, "\n", 0); - g_free (output); - line_p = lines; - /* find the beginning of the (data) section we are interested in */ - while (line_p && *line_p && !g_str_has_prefix (*line_p, "data")) - line_p++; - if (!line_p || !(*line_p)) { - /* error is already populated */ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse xfs file system information"); - g_strfreev (lines); - bd_fs_xfs_info_free (ret); - return FALSE; - } - - /* extract data from something like this: "data = bsize=4096 blocks=262400, imaxpct=25" */ - val_start = strchr (*line_p, '='); - val_start++; - while (isspace (*val_start)) - val_start++; - if (g_str_has_prefix (val_start, "bsize")) { - val_start = strchr (val_start, '='); - val_start++; - ret->block_size = g_ascii_strtoull (val_start, NULL, 0); - } else { - /* error is already populated */ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse xfs file system information"); - g_strfreev (lines); - bd_fs_xfs_info_free (ret); - return FALSE; - } - while (isdigit (*val_start) || isspace(*val_start)) - val_start++; - if (g_str_has_prefix (val_start, "blocks")) { - val_start = strchr (val_start, '='); - val_start++; - ret->block_count = g_ascii_strtoull (val_start, NULL, 0); - } else { - /* error is already populated */ - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse xfs file system information"); - g_strfreev (lines); - bd_fs_xfs_info_free (ret); - return FALSE; - } - g_strfreev (lines); - - return ret; -} - -/** - * bd_fs_xfs_resize: - * @mpoint: the mount point of the file system to resize - * @new_size: new requested size for the file system *in file system blocks* (see bd_fs_xfs_get_info()) - * (if 0, the file system is adapted to the underlying block device) - * @extra: (allow-none) (array zero-terminated=1): extra options for the resize (right now - * passed to the 'xfs_growfs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether the file system mounted on @mpoint was successfully resized or not - * - * Tech category: %BD_FS_TECH_XFS-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_xfs_resize (const gchar *mpoint, guint64 new_size, const BDExtraArg **extra, GError **error) { - const gchar *args[5] = {"xfs_growfs", NULL, NULL, NULL, NULL}; - gchar *size_str = NULL; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_XFS_GROWFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - if (new_size != 0) { - args[1] = "-D"; - /* xfs_growfs doesn't understand bytes, just a number of blocks */ - size_str = g_strdup_printf ("%"G_GUINT64_FORMAT, new_size); - args[2] = size_str; - args[3] = mpoint; - } else - args[1] = mpoint; - - ret = bd_utils_exec_and_report_error (args, extra, error); - - g_free (size_str); - return ret; -} - -/** - * bd_fs_vfat_mkfs: - * @device: the device to create a new vfat fs on - * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now - * passed to the 'mkfs.vfat' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether a new vfat fs was successfully created on @device or not - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_MKFS - */ -gboolean bd_fs_vfat_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { - const gchar *args[4] = {"mkfs.vfat", "-I", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_MKFSVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * bd_fs_vfat_wipe: - * @device: the device to wipe an vfat signature from - * @error: (out): place to store error (if any) - * - * Returns: whether an vfat signature was successfully wiped from the @device or - * not - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_vfat_wipe (const gchar *device, GError **error) { - return wipe_fs (device, "vfat", TRUE, error); -} - -/** - * bd_fs_vfat_check: - * @device: the device containing the file system to check - * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now - * passed to the 'fsck.vfat' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an vfat file system on the @device is clean or not - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_vfat_check (const gchar *device, const BDExtraArg **extra, GError **error) { - const gchar *args[4] = {"fsck.vfat", "-n", device, NULL}; - gint status = 0; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_FSCKVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - ret = bd_utils_exec_and_report_status_error (args, extra, &status, error); - if (!ret && (status == 1)) { - /* no error should be reported for exit code 1 -- Recoverable errors have been detected */ - g_clear_error (error); - } - return ret; -} - -/** - * bd_fs_vfat_repair: - * @device: the device containing the file system to repair - * @extra: (allow-none) (array zero-terminated=1): extra options for the repair (right now - * passed to the 'fsck.vfat' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether an vfat file system on the @device was successfully repaired - * (if needed) or not (error is set in that case) - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_vfat_repair (const gchar *device, const BDExtraArg **extra, GError **error) { - const gchar *args[4] = {"fsck.vfat", "-a", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_FSCKVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * bd_fs_vfat_set_label: - * @device: the device containing the file system to set label for - * @label: label to set - * @error: (out): place to store error (if any) - * - * Returns: whether the label of vfat file system on the @device was - * successfully set or not - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError **error) { - const gchar *args[4] = {"fatlabel", device, label, NULL}; - - if (!check_deps (&avail_deps, DEPS_FATLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, NULL, error); -} - -/** - * bd_fs_vfat_get_info: - * @device: the device containing the file system to get info for - * @error: (out): place to store error (if any) - * - * Returns: (transfer full): information about the file system on @device or - * %NULL in case of error - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_QUERY - */ -BDFSVfatInfo* bd_fs_vfat_get_info (const gchar *device, GError **error) { - const gchar *args[4] = {"fsck.vfat", "-nv", device, NULL}; - blkid_probe probe = NULL; - gint fd = 0; - gint status = 0; - gboolean success = FALSE; - const gchar *value = NULL; - BDFSVfatInfo *ret = NULL; - gchar *output = NULL; - gchar **lines = NULL; - gchar **line_p = NULL; - gboolean have_cluster_size = FALSE; - gboolean have_cluster_count = FALSE; - guint64 full_cluster_count = 0; - guint64 cluster_count = 0; - gchar **key_val = NULL; - gint scanned = 0; - - if (!check_deps (&avail_deps, DEPS_FSCKVFAT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - probe = blkid_new_probe (); - if (!probe) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - return FALSE; - } - - fd = open (device, O_RDWR|O_CLOEXEC); - if (fd == -1) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - blkid_free_probe (probe); - return FALSE; - } - - status = blkid_probe_set_device (probe, fd, 0, 0); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to create a probe for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return FALSE; - } - - blkid_probe_enable_partitions(probe, 1); - - status = blkid_do_probe (probe); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to probe the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return FALSE; - } - - ret = g_new0 (BDFSVfatInfo, 1); - - status = blkid_probe_has_value (probe, "LABEL"); - - if (status == 0) - ret->label = g_strdup (""); - else { - status = blkid_probe_lookup_value (probe, "LABEL", &value, NULL); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get label for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return FALSE; - } - - ret->label = g_strdup (value); - } - - status = blkid_probe_lookup_value (probe, "UUID", &value, NULL); - if (status != 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get label for the device '%s'", device); - blkid_free_probe (probe); - synced_close (fd); - return FALSE; - } - - ret->uuid = g_strdup (value); - - blkid_free_probe (probe); - synced_close (fd); - - success = bd_utils_exec_and_capture_output (args, NULL, &output, error); - if (!success) - /* error is already populated */ - return FALSE; - - lines = g_strsplit (output, "\n", 0); - g_free (output); - for (line_p=lines; *line_p && (!have_cluster_size || !have_cluster_count); line_p++) { - if (!have_cluster_size && g_str_has_suffix (*line_p, "bytes per cluster")) { - ret->cluster_size = g_ascii_strtoull (*line_p, NULL, 0); - have_cluster_size = TRUE; - } else if (!have_cluster_count && g_str_has_prefix (*line_p, device)) { - key_val = g_strsplit (*line_p, ",", 2); - scanned = sscanf (key_val[1], " %" G_GUINT64_FORMAT "/" "%" G_GUINT64_FORMAT " clusters", - &full_cluster_count, &cluster_count); - if (scanned != 2) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get number of FAT clusters for '%s'", device); - return FALSE; - } - ret->cluster_count = cluster_count; - ret->free_cluster_count = cluster_count - full_cluster_count; - have_cluster_count = TRUE; - g_strfreev (key_val); - } - } - g_strfreev (lines); - - return ret; -} - -/** - * bd_fs_vfat_resize: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system (if 0, the file system is - * adapted to the underlying block device) - * @error: (out): place to store error (if any) - * - * Returns: whether the file system on @device was successfully resized or not - * - * Tech category: %BD_FS_TECH_VFAT-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_vfat_resize (const gchar *device, guint64 new_size, GError **error) { - PedDevice *ped_dev = NULL; - PedGeometry geom = {0}; - PedGeometry new_geom = {0}; - PedFileSystem *fs = NULL; - PedSector start = 0; - PedSector length = 0; - gint status = 0; - guint64 progress_id = 0; - gchar *msg = NULL; - - msg = g_strdup_printf ("Started resizing vfat filesystem on the device '%s'", device); - progress_id = bd_utils_report_started (msg); - g_free (msg); - - ped_dev = ped_device_get (device); - if (!ped_dev) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get ped device for the device '%s'", device); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - status = ped_device_open (ped_dev); - if (status == 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to get open the device '%s'", device); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - status = ped_geometry_init (&geom, ped_dev, start, ped_dev->length); - if (status == 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to initialize geometry for the device '%s'", device); - ped_device_close (ped_dev); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - fs = ped_file_system_open(&geom); - if (!fs) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to read the filesystem on the device '%s'", device); - ped_device_close (ped_dev); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - if (new_size == 0) - length = ped_dev->length; - else - length = (PedSector) ((PedSector) new_size / ped_dev->sector_size); - - status = ped_geometry_init(&new_geom, ped_dev, start, length); - if (status == 0) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_FAIL, - "Failed to initialize new geometry for the filesystem on '%s'", device); - ped_file_system_close (fs); - ped_device_close (ped_dev); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - status = ped_file_system_resize(fs, &new_geom, NULL); - if (status == 0) { - set_parted_error (error, BD_FS_ERROR_FAIL); - g_prefix_error (error, "Failed to resize the filesystem on '%s'", device); - ped_file_system_close (fs); - ped_device_close (ped_dev); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - ped_file_system_close (fs); - ped_device_close (ped_dev); - bd_utils_report_finished (progress_id, "Completed"); - - return TRUE; - -} - -/** - * bd_fs_ntfs_mkfs: - * @device: the device to create a new ntfs fs on - * @extra: (allow-none) (array zero-terminated=1): extra options for the creation (right now - * passed to the 'mkntfs' utility) - * @error: (out): place to store error (if any) - * - * Returns: whether a new NTFS fs was successfully created on @device or not - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_MKFS - */ -gboolean bd_fs_ntfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) { - const gchar *args[5] = {"mkntfs", "-f", "-F", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_MKNTFS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, extra, error); -} - -/** - * bd_fs_ntfs_wipe: - * @device: the device to wipe an ntfs signature from - * @error: (out): place to store error (if any) - * - * Returns: whether an ntfs signature was successfully wiped from the @device or not - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_WIPE - */ -gboolean bd_fs_ntfs_wipe (const gchar *device, GError **error) { - return wipe_fs (device, "ntfs", TRUE, error); -} - -/** - * bd_fs_ntfs_check: - * @device: the device containing the file system to check - * @error: (out): place to store error (if any) - * - * Returns: whether an ntfs file system on the @device is clean or not - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_CHECK - */ -gboolean bd_fs_ntfs_check (const gchar *device, GError **error) { - const gchar *args[4] = {"ntfsfix", "-n", device, NULL}; - gint status = 0; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_NTFSFIX_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - ret = bd_utils_exec_and_report_status_error (args, NULL, &status, error); - if (!ret && (status == 1)) { - /* no error should be reported for exit code 1 -- Recoverable errors have been detected */ - g_clear_error (error); - } - return ret; -} - -/** - * bd_fs_ntfs_repair: - * @device: the device containing the file system to repair - * @error: (out): place to store error (if any) - * - * Returns: whether an NTFS file system on the @device was successfully repaired - * (if needed) or not (error is set in that case) - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_REPAIR - */ -gboolean bd_fs_ntfs_repair (const gchar *device, GError **error) { - const gchar *args[4] = {"ntfsfix", "-d", device, NULL}; - - if (!check_deps (&avail_deps, DEPS_NTFSFIX_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, NULL, error); -} - -/** - * bd_fs_ntfs_set_label: - * @device: the device containing the file system to set the label for - * @label: label to set - * @error: (out): place to store error (if any) - * - * Returns: whether the label of the NTFS file system on the @device was - * successfully set or not - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_SET_LABEL - */ -gboolean bd_fs_ntfs_set_label (const gchar *device, const gchar *label, GError **error) { - const gchar *args[4] = {"ntfslabel", device, label, NULL}; - - if (!check_deps (&avail_deps, DEPS_NTFSLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - return bd_utils_exec_and_report_error (args, NULL, error); -} - -/** - * bd_fs_ntfs_resize: - * @device: the device the file system of which to resize - * @new_size: new requested size for the file system in bytes (if 0, the file system - * is adapted to the underlying block device) - * @error: (out): place to store error (if any) - * - * Returns: whether the file system on @device was successfully resized or not - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_RESIZE - */ -gboolean bd_fs_ntfs_resize (const gchar *device, guint64 new_size, GError **error) { - const gchar *args[5] = {"ntfsresize", NULL, NULL, NULL, NULL}; - gboolean ret = FALSE; - - if (!check_deps (&avail_deps, DEPS_NTFSRESIZE_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - if (new_size != 0) { - args[1] = "-s"; - args[2] = g_strdup_printf ("%"G_GUINT64_FORMAT, new_size); - args[3] = device; - } else { - args[1] = device; - } - ret = bd_utils_exec_and_report_error (args, NULL, error); - - g_free ((gchar *) args[2]); - return ret; -} - -/** - * bd_fs_ntfs_get_info: - * @device: the device containing the file system to get info for (device must - not be mounted, trying to get info for a mounted device will result - in an error) - * @error: (out): place to store error (if any) - * - * Returns: (transfer full): information about the file system on @device or - * %NULL in case of error - * - * Tech category: %BD_FS_TECH_NTFS-%BD_FS_TECH_MODE_QUERY - */ -BDFSNtfsInfo* bd_fs_ntfs_get_info (const gchar *device, GError **error) { - const gchar *args[3] = {"ntfscluster", device, NULL}; - gboolean success = FALSE; - gchar *output = NULL; - BDFSNtfsInfo *ret = NULL; - gchar **lines = NULL; - gchar **line_p = NULL; - gchar *val_start = NULL; - g_autofree gchar* mountpoint = NULL; - - if (!check_deps (&avail_deps, DEPS_NTFSCLUSTER_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - - mountpoint = bd_fs_get_mountpoint (device, error); - if (mountpoint != NULL) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_NOT_MOUNTED, - "Can't get NTFS file system information for '%s': Device is mounted.", device); - return NULL; - } else { - if (*error != NULL) { - g_prefix_error (error, "Error when trying to get mountpoint for '%s': ", device); - return NULL; - } - } - - success = bd_utils_exec_and_capture_output (args, NULL, &output, error); - if (!success) - /* error is already populated */ - return FALSE; - - ret = g_new0 (BDFSNtfsInfo, 1); - lines = g_strsplit (output, "\n", 0); - g_free (output); - line_p = lines; - /* find the beginning of the (data) section we are interested in */ - while (line_p && *line_p && !g_str_has_prefix (*line_p, "bytes per volume")) - line_p++; - if (!line_p || !(*line_p)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NTFS file system information"); - g_strfreev (lines); - bd_fs_ntfs_info_free (ret); - return FALSE; - } - - /* extract data from something like this: "bytes per volume : 998240256" */ - val_start = strchr (*line_p, ':'); - val_start++; - ret->size = g_ascii_strtoull (val_start, NULL, 0); - - while (line_p && *line_p && !g_str_has_prefix (*line_p, "bytes of free space")) - line_p++; - if (!line_p || !(*line_p)) { - g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NTFS file system information"); - g_strfreev (lines); - bd_fs_ntfs_info_free (ret); - return FALSE; - } - - /* extract data from something like this: "bytes of free space : 992759808" */ - val_start = strchr (*line_p, ':'); - val_start++; - ret->free_space = g_ascii_strtoull (val_start, NULL, 0); - - g_strfreev (lines); - - return ret; } diff -Nru libblockdev-2.14/src/plugins/fs.h libblockdev-2.16/src/plugins/fs.h --- libblockdev-2.14/src/plugins/fs.h 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/fs.h 2018-02-08 11:10:41.000000000 +0000 @@ -1,5 +1,4 @@ #include -#include #ifndef BD_FS #define BD_FS @@ -19,60 +18,9 @@ BD_FS_ERROR_TECH_UNAVAIL, } BDFsError; -typedef struct BDFSExtInfo { - gchar *label; - gchar *uuid; - gchar *state; - guint64 block_size; - guint64 block_count; - guint64 free_blocks; -} BDFSExtInfo; - -typedef struct BDFSExtInfo BDFSExt4Info; -typedef struct BDFSExtInfo BDFSExt3Info; -typedef struct BDFSExtInfo BDFSExt2Info; - -BDFSExt2Info* bd_fs_ext2_info_copy (BDFSExt2Info *data); -void bd_fs_ext2_info_free (BDFSExt2Info *data); - -BDFSExt3Info* bd_fs_ext3_info_copy (BDFSExt3Info *data); -void bd_fs_ext3_info_free (BDFSExt3Info *data); - -BDFSExt4Info* bd_fs_ext4_info_copy (BDFSExt4Info *data); -void bd_fs_ext4_info_free (BDFSExt4Info *data); - -typedef struct BDFSXfsInfo { - gchar *label; - gchar *uuid; - guint64 block_size; - guint64 block_count; -} BDFSXfsInfo; - -BDFSXfsInfo* bd_fs_xfs_info_copy (BDFSXfsInfo *data); -void bd_fs_xfs_info_free (BDFSXfsInfo *data); - -typedef struct BDFSVfatInfo { - gchar *label; - gchar *uuid; - guint64 cluster_size; - guint64 cluster_count; - guint64 free_cluster_count; -} BDFSVfatInfo; - -BDFSVfatInfo* bd_fs_vfat_info_copy (BDFSVfatInfo *data); -void bd_fs_vfat_info_free (BDFSVfatInfo *data); - -typedef struct BDFSNtfsInfo { - guint64 size; - guint64 free_space; -} BDFSNtfsInfo; - -BDFSNtfsInfo* bd_fs_ntfs_info_copy (BDFSNtfsInfo *data); -void bd_fs_ntfs_info_free (BDFSNtfsInfo *data); - /* XXX: where the file systems start at the enum of technologies */ -#define FS_OFFSET 2 -#define LAST_FS 7 +#define BD_FS_OFFSET 2 +#define BD_FS_LAST_FS 7 typedef enum { BD_FS_TECH_GENERIC = 0, BD_FS_TECH_MOUNT = 1, @@ -85,7 +33,7 @@ } BDFSTech; /* XXX: number of the highest bit of all modes */ -#define FS_MODE_LAST 6 +#define BD_FS_MODE_LAST 6 typedef enum { BD_FS_TECH_MODE_MKFS = 1 << 0, BD_FS_TECH_MODE_WIPE = 1 << 1, @@ -112,77 +60,11 @@ gboolean bd_fs_is_tech_avail (BDFSTech tech, guint64 mode, GError **error); -gboolean bd_fs_wipe (const gchar *device, gboolean all, GError **error); -gboolean bd_fs_clean (const gchar *device, GError **error); -gchar* bd_fs_get_fstype (const gchar *device, GError **error); - -gboolean bd_fs_unmount (const gchar *spec, gboolean lazy, gboolean force, const BDExtraArg **extra, GError **error); -gboolean bd_fs_mount (const gchar *device, const gchar *mountpoint, const gchar *fstype, const gchar *options, const BDExtraArg **extra, GError **error); -gchar* bd_fs_get_mountpoint (const gchar *device, GError **error); - -gboolean bd_fs_resize (const gchar *device, guint64 new_size, GError **error); -gboolean bd_fs_repair (const gchar *device, GError **error); -gboolean bd_fs_check (const gchar *device, GError **error); -gboolean bd_fs_set_label (const gchar *device, const gchar *label, GError **error); - -typedef enum { - BD_FS_OFFLINE_SHRINK = 1 << 1, - BD_FS_OFFLINE_GROW = 1 << 2, - BD_FS_ONLINE_SHRINK = 1 << 3, - BD_FS_ONLINE_GROW = 1 << 4 -} BDFsResizeFlags; - -gboolean bd_fs_can_resize (const gchar *type, BDFsResizeFlags *mode, gchar **required_utility, GError **error); -gboolean bd_fs_can_check (const gchar *type, gchar **required_utility, GError **error); -gboolean bd_fs_can_repair (const gchar *type, gchar **required_utility, GError **error); -gboolean bd_fs_can_set_label (const gchar *type, gchar **required_utility, GError **error); - -gboolean bd_fs_ext2_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext2_wipe (const gchar *device, GError **error); -gboolean bd_fs_ext2_check (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext2_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext2_set_label (const gchar *device, const gchar *label, GError **error); -BDFSExt2Info* bd_fs_ext2_get_info (const gchar *device, GError **error); -gboolean bd_fs_ext2_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error); - -gboolean bd_fs_ext3_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext3_wipe (const gchar *device, GError **error); -gboolean bd_fs_ext3_check (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext3_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext3_set_label (const gchar *device, const gchar *label, GError **error); -BDFSExt3Info* bd_fs_ext3_get_info (const gchar *device, GError **error); -gboolean bd_fs_ext3_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error); - -gboolean bd_fs_ext4_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext4_wipe (const gchar *device, GError **error); -gboolean bd_fs_ext4_check (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext4_repair (const gchar *device, gboolean unsafe, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ext4_set_label (const gchar *device, const gchar *label, GError **error); -BDFSExt4Info* bd_fs_ext4_get_info (const gchar *device, GError **error); -gboolean bd_fs_ext4_resize (const gchar *device, guint64 new_size, const BDExtraArg **extra, GError **error); - -gboolean bd_fs_xfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_xfs_wipe (const gchar *device, GError **error); -gboolean bd_fs_xfs_check (const gchar *device, GError **error); -gboolean bd_fs_xfs_repair (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_xfs_set_label (const gchar *device, const gchar *label, GError **error); -BDFSXfsInfo* bd_fs_xfs_get_info (const gchar *device, GError **error); -gboolean bd_fs_xfs_resize (const gchar *mpoint, guint64 new_size, const BDExtraArg **extra, GError **error); - -gboolean bd_fs_vfat_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_vfat_wipe (const gchar *device, GError **error); -gboolean bd_fs_vfat_check (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_vfat_repair (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError **error); -BDFSVfatInfo* bd_fs_vfat_get_info (const gchar *device, GError **error); -gboolean bd_fs_vfat_resize (const gchar *device, guint64 new_size, GError **error); - -gboolean bd_fs_ntfs_mkfs (const gchar *device, const BDExtraArg **extra, GError **error); -gboolean bd_fs_ntfs_wipe (const gchar *device, GError **error); -gboolean bd_fs_ntfs_check (const gchar *device, GError **error); -gboolean bd_fs_ntfs_repair (const gchar *device, GError **error); -gboolean bd_fs_ntfs_set_label (const gchar *device, const gchar *label, GError **error); -BDFSNtfsInfo* bd_fs_ntfs_get_info (const gchar *device, GError **error); -gboolean bd_fs_ntfs_resize (const gchar *device, guint64 new_size, GError **error); +#endif /* BD_FS */ -#endif /* BD_PART */ +#include "fs/ext.h" +#include "fs/generic.h" +#include "fs/mount.h" +#include "fs/ntfs.h" +#include "fs/vfat.h" +#include "fs/xfs.h" diff -Nru libblockdev-2.14/src/plugins/kbd.c libblockdev-2.16/src/plugins/kbd.c --- libblockdev-2.14/src/plugins/kbd.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/kbd.c 2018-02-08 11:10:41.000000000 +0000 @@ -46,9 +46,6 @@ /* "C" locale to get the locale-agnostic error messages */ static locale_t c_locale = (locale_t) 0; -static gboolean have_kernel_module (const gchar *module_name, GError **error); - - static volatile guint avail_deps = 0; static GMutex deps_check_lock; @@ -75,7 +72,7 @@ guint i = 0; gboolean status = FALSE; - ret = have_kernel_module ("zram", &error); + ret = bd_utils_have_kernel_module ("zram", &error); if (!ret) { if (error) { g_warning("Cannot load the kbd plugin: %s" , error->message); @@ -138,7 +135,7 @@ * */ void bd_kbd_close () { - c_locale = (locale_t) 0; + freelocale (c_locale); } /** @@ -208,143 +205,6 @@ g_free (data); } -static gboolean have_kernel_module (const gchar *module_name, GError **error) { - gint ret = 0; - struct kmod_ctx *ctx = NULL; - struct kmod_module *mod = NULL; - gchar *null_config = NULL; - const gchar *path = NULL; - gboolean have_path = FALSE; - - ctx = kmod_new (NULL, (const gchar * const*) &null_config); - if (!ctx) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_KMOD_INIT_FAIL, - "Failed to initialize kmod context"); - return FALSE; - } - /* prevent libkmod from spamming our STDERR */ - kmod_set_log_priority(ctx, LOG_CRIT); - - ret = kmod_module_new_from_name (ctx, module_name, &mod); - if (ret < 0) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_FAIL, - "Failed to get the module: %s", strerror_l (-ret, c_locale)); - kmod_unref (ctx); - return FALSE; - } - - path = kmod_module_get_path (mod); - have_path = (path != NULL) && (g_strcmp0 (path, "") != 0); - kmod_module_unref (mod); - kmod_unref (ctx); - - return have_path; -} - -static gboolean load_kernel_module (const gchar *module_name, const gchar *options, GError **error) { - gint ret = 0; - struct kmod_ctx *ctx = NULL; - struct kmod_module *mod = NULL; - gchar *null_config = NULL; - - ctx = kmod_new (NULL, (const gchar * const*) &null_config); - if (!ctx) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_KMOD_INIT_FAIL, - "Failed to initialize kmod context"); - return FALSE; - } - /* prevent libkmod from spamming our STDERR */ - kmod_set_log_priority(ctx, LOG_CRIT); - - ret = kmod_module_new_from_name (ctx, module_name, &mod); - if (ret < 0) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_FAIL, - "Failed to get the module: %s", strerror_l (-ret, c_locale)); - kmod_unref (ctx); - return FALSE; - } - - if (!kmod_module_get_path (mod)) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_NOEXIST, - "Module '%s' doesn't exist", module_name); - kmod_module_unref (mod); - kmod_unref (ctx); - return FALSE; - } - - /* module, flags, options */ - ret = kmod_module_insert_module (mod, 0, options); - if (ret < 0) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_FAIL, - "Failed to load the module '%s' with options '%s': %s", - module_name, options, strerror_l (-ret, c_locale)); - kmod_module_unref (mod); - kmod_unref (ctx); - return FALSE; - } - - kmod_module_unref (mod); - kmod_unref (ctx); - return TRUE; -} - -static gboolean unload_kernel_module (const gchar *module_name, GError **error) { - gint ret = 0; - struct kmod_ctx *ctx = NULL; - struct kmod_module *mod = NULL; - struct kmod_list *list = NULL; - struct kmod_list *cur = NULL; - gchar *null_config = NULL; - gboolean found = FALSE; - - ctx = kmod_new (NULL, (const gchar * const*) &null_config); - if (!ctx) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_KMOD_INIT_FAIL, - "Failed to initialize kmod context"); - return FALSE; - } - /* prevent libkmod from spamming our STDERR */ - kmod_set_log_priority(ctx, LOG_CRIT); - - ret = kmod_module_new_from_loaded (ctx, &list); - if (ret < 0) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_FAIL, - "Failed to get the module: %s", strerror_l (-ret, c_locale)); - kmod_unref (ctx); - return FALSE; - } - - for (cur=list; !found && cur != NULL; cur = kmod_list_next(list, cur)) { - mod = kmod_module_get_module (cur); - if (g_strcmp0 (kmod_module_get_name (mod), module_name) == 0) - found = TRUE; - else - kmod_module_unref (mod); - } - - if (!found) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_NOEXIST, - "Module '%s' is not loaded", module_name); - kmod_unref (ctx); - return FALSE; - } - - /* module, flags */ - ret = kmod_module_remove_module (mod, 0); - if (ret < 0) { - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_FAIL, - "Failed to unload the module '%s': %s", - module_name, strerror_l (-ret, c_locale)); - kmod_module_unref (mod); - kmod_unref (ctx); - return FALSE; - } - - kmod_module_unref (mod); - kmod_unref (ctx); - return TRUE; -} - /** * bd_kbd_zram_create_devices: * @num_devices: number of devices to create @@ -371,19 +231,19 @@ progress_id = bd_utils_report_started ("Started creating zram devices"); opts = g_strdup_printf ("num_devices=%"G_GUINT64_FORMAT, num_devices); - success = load_kernel_module ("zram", opts, error); + success = bd_utils_load_kernel_module ("zram", opts, error); /* maybe it's loaded? Try to unload it first */ - if (!success && g_error_matches (*error, BD_KBD_ERROR, BD_KBD_ERROR_MODULE_FAIL)) { + if (!success && g_error_matches (*error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_FAIL)) { g_clear_error (error); - success = unload_kernel_module ("zram", error); + success = bd_utils_unload_kernel_module ("zram", error); if (!success) { g_prefix_error (error, "zram module already loaded: "); g_free (opts); bd_utils_report_finished (progress_id, (*error)->message); return FALSE; } - success = load_kernel_module ("zram", opts, error); + success = bd_utils_load_kernel_module ("zram", opts, error); if (!success) { g_free (opts); bd_utils_report_finished (progress_id, (*error)->message); @@ -450,7 +310,7 @@ guint64 progress_id = 0; progress_id = bd_utils_report_started ("Started destroying zram devices"); - ret = unload_kernel_module ("zram", error); + ret = bd_utils_unload_kernel_module ("zram", error); if (!ret && (*error)) bd_utils_report_finished (progress_id, (*error)->message); else @@ -496,7 +356,7 @@ progress_id = bd_utils_report_started ("Started adding new zram device"); if (access ("/sys/class/zram-control/hot_add", R_OK) != 0) { - success = load_kernel_module ("zram", NULL, error); + success = bd_utils_load_kernel_module ("zram", NULL, error); if (!success) { g_prefix_error (error, "Failed to load the zram kernel module: "); return FALSE; diff -Nru libblockdev-2.14/src/plugins/kbd.h libblockdev-2.16/src/plugins/kbd.h --- libblockdev-2.14/src/plugins/kbd.h 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/kbd.h 2018-02-08 11:10:41.000000000 +0000 @@ -8,9 +8,6 @@ #define BD_KBD_ERROR bd_kbd_error_quark () typedef enum { BD_KBD_ERROR_INVAL, - BD_KBD_ERROR_KMOD_INIT_FAIL, - BD_KBD_ERROR_MODULE_FAIL, - BD_KBD_ERROR_MODULE_NOEXIST, BD_KBD_ERROR_ZRAM_NOEXIST, BD_KBD_ERROR_ZRAM_INVAL, BD_KBD_ERROR_BCACHE_PARSE, diff -Nru libblockdev-2.14/src/plugins/Makefile.am libblockdev-2.16/src/plugins/Makefile.am --- libblockdev-2.14/src/plugins/Makefile.am 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/Makefile.am 2018-02-08 11:10:41.000000000 +0000 @@ -1,3 +1,7 @@ +if WITH_FS +SUBDIRS = . fs +endif + lib_LTLIBRARIES = if WITH_BTRFS @@ -48,11 +52,6 @@ lib_LTLIBRARIES += libbd_part.la endif -if WITH_FS -lib_LTLIBRARIES += libbd_fs.la -endif - - if WITH_S390 lib_LTLIBRARIES += libbd_s390.la endif @@ -132,8 +131,8 @@ endif if WITH_KBD -libbd_kbd_la_CFLAGS = $(GLIB_CFLAGS) $(KMOD_CFLAGS) $(BYTESIZE_CFLAGS) -Wall -Wextra -Werror -libbd_kbd_la_LIBADD = $(GLIB_LIBS) $(KMOD_LIBS) $(BYTESIZE_LIBS) ${builddir}/../utils/libbd_utils.la +libbd_kbd_la_CFLAGS = $(GLIB_CFLAGS) $(BYTESIZE_CFLAGS) -Wall -Wextra -Werror +libbd_kbd_la_LIBADD = $(GLIB_LIBS) $(BYTESIZE_LIBS) ${builddir}/../utils/libbd_utils.la libbd_kbd_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 2:0:0 -Wl,--no-undefined libbd_kbd_la_CPPFLAGS = -I${builddir}/../../include/ libbd_kbd_la_SOURCES = kbd.c kbd.h check_deps.c check_deps.h @@ -156,14 +155,6 @@ libbd_part_la_SOURCES = part.c part.h check_deps.c check_deps.h endif -if WITH_FS -libbd_fs_la_CFLAGS = $(GLIB_CFLAGS) $(BLKID_CFLAGS) $(PARTED_CFLAGS) $(PARTED_FS_CFLAGS) $(MOUNT_CFLAGS) -Wall -Wextra -Werror -libbd_fs_la_LIBADD = $(GLIB_LIBS) $(BLKID_LIBS) $(PARTED_LIBS) $(PARTED_FS_LIBS) $(MOUNT_LIBS) ${builddir}/../utils/libbd_utils.la ${builddir}/libbd_part_err.la -libbd_fs_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 2:0:0 -Wl,--no-undefined -libbd_fs_la_CPPFLAGS = -I${builddir}/../../include/ -libbd_fs_la_SOURCES = fs.c fs.h check_deps.c check_deps.h -endif - if WITH_PART_O_WITH_FS libbd_part_err_la_CFLAGS = $(GLIB_CFLAGS) $(PARTED_CFLAGS) $(PARTED_FS_CFLAGS) -Wall -Wextra -Werror libbd_part_err_la_LIBADD = $(GLIB_LIBS) $(PARTED_LIBS) $(PARTED_FS_LIBS) ${builddir}/../utils/libbd_utils.la diff -Nru libblockdev-2.14/src/plugins/part.c libblockdev-2.16/src/plugins/part.c --- libblockdev-2.14/src/plugins/part.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/part.c 2018-02-08 11:10:41.000000000 +0000 @@ -1553,6 +1553,8 @@ * not * * Note: Unsets all the other flags on the partition. + * Only GPT-specific flags and the legacy boot flag are supported on GPT + * partition tables. * * Tech category: %BD_PART_TECH_MODE_MODIFY_PART + the tech according to the partition table type */ @@ -1613,37 +1615,39 @@ return FALSE; } - ped_part = ped_disk_get_partition (ped_disk, part_num); - if (!ped_part) { - set_parted_error (error, BD_PART_ERROR_FAIL); - g_prefix_error (error, "Failed to get partition '%d' on device '%s'", part_num, disk); - ped_disk_destroy (ped_disk); - ped_device_destroy (dev); - bd_utils_report_finished (progress_id, (*error)->message); - return FALSE; - } - - /* our flags are 1s shifted to the bit determined by parted's flags - * (i.e. 1 << 3 instead of 3, etc.) */ - for (i=1; i <= (int) log2 ((double)BD_PART_FLAG_BASIC_LAST); i++) { - if ((1 << i) & flags) - status = ped_partition_set_flag (ped_part, (PedPartitionFlag) i, (int) 1); - else if (ped_partition_is_flag_available (ped_part, (PedPartitionFlag) i)) - status = ped_partition_set_flag (ped_part, (PedPartitionFlag) i, (int) 0); - if (status == 0) { + /* Do not let libparted touch gpt partition tables */ + if (g_strcmp0 (ped_disk->type->name, "gpt") == 0) { + ret = set_gpt_flags (disk, part_num, flags, error); + } else { + ped_part = ped_disk_get_partition (ped_disk, part_num); + if (!ped_part) { set_parted_error (error, BD_PART_ERROR_FAIL); - g_prefix_error (error, "Failed to set flag on the partition '%d' on device '%s'", part_num, disk); + g_prefix_error (error, "Failed to get partition '%d' on device '%s'", part_num, disk); ped_disk_destroy (ped_disk); ped_device_destroy (dev); bd_utils_report_finished (progress_id, (*error)->message); return FALSE; } - } - ret = disk_commit (ped_disk, disk, error); + /* our flags are 1s shifted to the bit determined by parted's flags + * (i.e. 1 << 3 instead of 3, etc.) */ + for (i=1; i <= (int) log2 ((double)BD_PART_FLAG_BASIC_LAST); i++) { + if ((1 << i) & flags) + status = ped_partition_set_flag (ped_part, (PedPartitionFlag) i, (int) 1); + else if (ped_partition_is_flag_available (ped_part, (PedPartitionFlag) i)) + status = ped_partition_set_flag (ped_part, (PedPartitionFlag) i, (int) 0); + if (status == 0) { + set_parted_error (error, BD_PART_ERROR_FAIL); + g_prefix_error (error, "Failed to set flag on the partition '%d' on device '%s'", part_num, disk); + ped_disk_destroy (ped_disk); + ped_device_destroy (dev); + bd_utils_report_finished (progress_id, (*error)->message); + return FALSE; + } + } - if (ret && (g_strcmp0 (ped_disk->type->name, "gpt") == 0)) - ret = set_gpt_flags (disk, part_num, flags, error); + ret = disk_commit (ped_disk, disk, error); + } ped_disk_destroy (ped_disk); ped_device_destroy (dev); diff -Nru libblockdev-2.14/src/plugins/part.h libblockdev-2.16/src/plugins/part.h --- libblockdev-2.14/src/plugins/part.h 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/part.h 2018-02-08 11:10:41.000000000 +0000 @@ -22,6 +22,19 @@ BD_PART_DISK_FLAG_GPT_PMBR_BOOT = 1 } BDPartDiskFlag; + +/** + * BDPartFlag: + * + * Partition flags supported by libblockdev. First part of the flags (up to + * @BD_PART_FLAG_BASIC_LAST) corresponds to the flags supported by libparted + * (see https://www.gnu.org/software/parted/manual/parted.html#set). Second + * part corresponds to the flags supported by sgdisk (GPT, see `sgdisk -A=list`). + * + * The only exception from the above is @BD_PART_FLAG_LEGACY_BOOT which is + * supported by libparted too but is GPT specific. + * + */ typedef enum { BD_PART_FLAG_BOOT = 1 << 1, BD_PART_FLAG_ROOT = 1 << 2, diff -Nru libblockdev-2.14/src/plugins/s390.c libblockdev-2.16/src/plugins/s390.c --- libblockdev-2.14/src/plugins/s390.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/plugins/s390.c 2018-02-08 11:10:41.000000000 +0000 @@ -154,15 +154,15 @@ */ gboolean bd_s390_dasd_format (const gchar *dasd, const BDExtraArg **extra, GError **error) { gboolean rc = FALSE; - gchar *dev = NULL; - const gchar *argv[8] = {"/sbin/dasdfmt", "-y", "-d", "cdl", "-b", "4096", dev, NULL}; + const gchar *argv[8] = {"/sbin/dasdfmt", "-y", "-d", "cdl", "-b", "4096", NULL, NULL}; if (!check_deps (&avail_deps, DEPS_DASDFMT_MASK, deps, DEPS_LAST, &deps_check_lock, error)) return FALSE; - dev = g_strdup_printf ("/dev/%s", dasd); + argv[6] = g_strdup_printf ("/dev/%s", dasd); + rc = bd_utils_exec_and_report_error (argv, extra, error); - g_free (dev); + g_free ((gchar *) argv[6]); return rc; } @@ -353,13 +353,8 @@ return FALSE; } - /* check dasd volume label; "VOL1" is a CDL formatted DASD, won't require formatting */ - if (dasd_info.format == DASD_FORMAT_CDL) { - return FALSE; - } - else { - return TRUE; - } + /* check dasd format */ + return dasd_info.format == DASD_FORMAT_LDL; } /** diff -Nru libblockdev-2.14/src/utils/blockdev-utils.pc.in libblockdev-2.16/src/utils/blockdev-utils.pc.in --- libblockdev-2.14/src/utils/blockdev-utils.pc.in 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/utils/blockdev-utils.pc.in 2018-02-08 11:10:41.000000000 +0000 @@ -5,7 +5,7 @@ Name: BlockDev-utils Description: A library with utility functions used by the libblockdev library -URL: https://github.com/rhinstaller/libblockdev +URL: https://github.com/storaged-project/libblockdev Version: @VERSION@ Requires: glib-2.0 Libs: -lbd_utils diff -Nru libblockdev-2.14/src/utils/exec.c libblockdev-2.16/src/utils/exec.c --- libblockdev-2.14/src/utils/exec.c 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/utils/exec.c 2018-02-08 11:10:41.000000000 +0000 @@ -728,6 +728,15 @@ } /** + * bd_utils_prog_reporting_initialized: + * + * Returns: TRUE if progress reporting has been initialized. + */ +gboolean bd_utils_prog_reporting_initialized () { + return prog_func != NULL; +} + +/** * bd_utils_report_started: * @msg: message describing the started task/action * diff -Nru libblockdev-2.14/src/utils/exec.h libblockdev-2.16/src/utils/exec.h --- libblockdev-2.14/src/utils/exec.h 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/utils/exec.h 2018-02-08 11:10:41.000000000 +0000 @@ -60,6 +60,7 @@ gboolean bd_utils_check_util_version (const gchar *util, const gchar *version, const gchar *version_arg, const gchar *version_regexp, GError **error); gboolean bd_utils_init_prog_reporting (BDUtilsProgFunc new_prog_func, GError **error); +gboolean bd_utils_prog_reporting_initialized (); guint64 bd_utils_report_started (gchar *msg); void bd_utils_report_progress (guint64 task_id, guint64 completion, gchar *msg); void bd_utils_report_finished (guint64 task_id, gchar *msg); diff -Nru libblockdev-2.14/src/utils/Makefile.am libblockdev-2.16/src/utils/Makefile.am --- libblockdev-2.14/src/utils/Makefile.am 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/utils/Makefile.am 2018-02-08 11:10:41.000000000 +0000 @@ -1,11 +1,11 @@ lib_LTLIBRARIES = libbd_utils.la -libbd_utils_la_CFLAGS = $(GLIB_CFLAGS) $(UDEV_CFLAGS) -Wall -Wextra -Werror +libbd_utils_la_CFLAGS = $(GLIB_CFLAGS) $(UDEV_CFLAGS) $(KMOD_CFLAGS) -Wall -Wextra -Werror libbd_utils_la_LDFLAGS = -version-info 3:0:1 -Wl,--no-undefined -libbd_utils_la_LIBADD = $(GLIB_LIBS) -lm $(GIO_LIBS) $(UDEV_LIBS) -libbd_utils_la_SOURCES = utils.h exec.c exec.h sizes.h extra_arg.c extra_arg.h dev_utils.c dev_utils.h +libbd_utils_la_LIBADD = $(GLIB_LIBS) -lm $(GIO_LIBS) $(UDEV_LIBS) $(KMOD_LIBS) +libbd_utils_la_SOURCES = utils.h exec.c exec.h sizes.h extra_arg.c extra_arg.h dev_utils.c dev_utils.h module.c module.h libincludedir = $(includedir)/blockdev -libinclude_HEADERS = utils.h exec.h sizes.h extra_arg.h dev_utils.h +libinclude_HEADERS = utils.h exec.h sizes.h extra_arg.h dev_utils.h module.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = ${builddir}/blockdev-utils.pc diff -Nru libblockdev-2.14/src/utils/module.c libblockdev-2.16/src/utils/module.c --- libblockdev-2.14/src/utils/module.c 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/utils/module.c 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Vojtech Trefny + */ + +#include +#include +#include +#include +#include + +#include "module.h" + + +/** + * bd_utils_module_error_quark: (skip) + */ +GQuark bd_utils_module_error_quark (void) +{ + return g_quark_from_static_string ("g-bd-utils-module-error-quark"); +} + +/** + * bd_utils_have_kernel_module: + * @module_name: name of the kernel module to check + * @error: (out): place to store error (if any) + * + * Returns: whether the @module_name was found in the system + */ +gboolean bd_utils_have_kernel_module (const gchar *module_name, GError **error) { + gint ret = 0; + struct kmod_ctx *ctx = NULL; + struct kmod_module *mod = NULL; + gchar *null_config = NULL; + const gchar *path = NULL; + gboolean have_path = FALSE; + locale_t c_locale = newlocale (LC_ALL_MASK, "C", (locale_t) 0); + + ctx = kmod_new (NULL, (const gchar * const*) &null_config); + if (!ctx) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_KMOD_INIT_FAIL, + "Failed to initialize kmod context"); + freelocale (c_locale); + return FALSE; + } + /* prevent libkmod from spamming our STDERR */ + kmod_set_log_priority(ctx, LOG_CRIT); + + ret = kmod_module_new_from_name (ctx, module_name, &mod); + if (ret < 0) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_FAIL, + "Failed to get the module: %s", strerror_l (-ret, c_locale)); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + path = kmod_module_get_path (mod); + have_path = (path != NULL) && (g_strcmp0 (path, "") != 0); + kmod_module_unref (mod); + kmod_unref (ctx); + freelocale (c_locale); + + return have_path; +} + +/** + * bd_utils_load_kernel_module: + * @module_name: name of the kernel module to load + * @options: (allow-none): module options + * @error: (out): place to store error (if any) + * + * Returns: whether the @module_name was successfully loaded or not + */ +gboolean bd_utils_load_kernel_module (const gchar *module_name, const gchar *options, GError **error) { + gint ret = 0; + struct kmod_ctx *ctx = NULL; + struct kmod_module *mod = NULL; + gchar *null_config = NULL; + locale_t c_locale = newlocale (LC_ALL_MASK, "C", (locale_t) 0); + + ctx = kmod_new (NULL, (const gchar * const*) &null_config); + if (!ctx) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_KMOD_INIT_FAIL, + "Failed to initialize kmod context"); + freelocale (c_locale); + return FALSE; + } + /* prevent libkmod from spamming our STDERR */ + kmod_set_log_priority(ctx, LOG_CRIT); + + ret = kmod_module_new_from_name (ctx, module_name, &mod); + if (ret < 0) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_FAIL, + "Failed to get the module: %s", strerror_l (-ret, c_locale)); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + if (!kmod_module_get_path (mod)) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_NOEXIST, + "Module '%s' doesn't exist", module_name); + kmod_module_unref (mod); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + /* module, flags, options */ + ret = kmod_module_insert_module (mod, 0, options); + if (ret < 0) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_FAIL, + "Failed to load the module '%s' with options '%s': %s", + module_name, options, strerror_l (-ret, c_locale)); + kmod_module_unref (mod); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + kmod_module_unref (mod); + kmod_unref (ctx); + freelocale (c_locale); + return TRUE; +} + +/** + * bd_utils_unload_kernel_module: + * @module_name: name of the kernel module to unload + * @error: (out): place to store error (if any) + * + * Returns: whether the @module_name was successfully unloaded or not + */ +gboolean bd_utils_unload_kernel_module (const gchar *module_name, GError **error) { + gint ret = 0; + struct kmod_ctx *ctx = NULL; + struct kmod_module *mod = NULL; + struct kmod_list *list = NULL; + struct kmod_list *cur = NULL; + gchar *null_config = NULL; + gboolean found = FALSE; + locale_t c_locale = newlocale (LC_ALL_MASK, "C", (locale_t) 0); + + ctx = kmod_new (NULL, (const gchar * const*) &null_config); + if (!ctx) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_KMOD_INIT_FAIL, + "Failed to initialize kmod context"); + freelocale (c_locale); + return FALSE; + } + /* prevent libkmod from spamming our STDERR */ + kmod_set_log_priority(ctx, LOG_CRIT); + + ret = kmod_module_new_from_loaded (ctx, &list); + if (ret < 0) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_FAIL, + "Failed to get the module: %s", strerror_l (-ret, c_locale)); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + for (cur=list; !found && cur != NULL; cur = kmod_list_next(list, cur)) { + mod = kmod_module_get_module (cur); + if (g_strcmp0 (kmod_module_get_name (mod), module_name) == 0) + found = TRUE; + else + kmod_module_unref (mod); + } + + if (!found) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_NOEXIST, + "Module '%s' is not loaded", module_name); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + /* module, flags */ + ret = kmod_module_remove_module (mod, 0); + if (ret < 0) { + g_set_error (error, BD_UTILS_MODULE_ERROR, BD_UTILS_MODULE_ERROR_FAIL, + "Failed to unload the module '%s': %s", + module_name, strerror_l (-ret, c_locale)); + kmod_module_unref (mod); + kmod_unref (ctx); + freelocale (c_locale); + return FALSE; + } + + kmod_module_unref (mod); + kmod_unref (ctx); + freelocale (c_locale); + return TRUE; +} diff -Nru libblockdev-2.14/src/utils/module.h libblockdev-2.16/src/utils/module.h --- libblockdev-2.14/src/utils/module.h 1970-01-01 00:00:00.000000000 +0000 +++ libblockdev-2.16/src/utils/module.h 2018-02-08 11:10:41.000000000 +0000 @@ -0,0 +1,20 @@ +#include + +#ifndef BD_UTILS_MODULE +#define BD_UTILS_MODULE + +GQuark bd_utils_module_error_quark (void); +#define BD_UTILS_MODULE_ERROR bd_utils_module_error_quark () +typedef enum { + BD_UTILS_MODULE_ERROR_KMOD_INIT_FAIL, + BD_UTILS_MODULE_ERROR_FAIL, + BD_UTILS_MODULE_ERROR_NOEXIST, + BD_UTILS_MODULE_ERROR_MODULE_CHECK_ERROR, +} BDUtilsModuleError; + +gboolean bd_utils_have_kernel_module (const gchar *module_name, GError **error); +gboolean bd_utils_load_kernel_module (const gchar *module_name, const gchar *options, GError **error); +gboolean bd_utils_unload_kernel_module (const gchar *module_name, GError **error); + + +#endif /* BD_UTILS_MODULE */ diff -Nru libblockdev-2.14/src/utils/utils.h libblockdev-2.16/src/utils/utils.h --- libblockdev-2.14/src/utils/utils.h 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/src/utils/utils.h 2018-02-08 11:10:41.000000000 +0000 @@ -5,6 +5,7 @@ #include "exec.h" #include "extra_arg.h" #include "dev_utils.h" +#include "module.h" /** * SECTION: utils diff -Nru libblockdev-2.14/tests/crypto_test.py libblockdev-2.16/tests/crypto_test.py --- libblockdev-2.14/tests/crypto_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/crypto_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -7,13 +7,24 @@ import six import locale -from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on, get_avail_locales, requires_locales +from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on, get_avail_locales, requires_locales, run_command from gi.repository import BlockDev, GLib PASSWD = "myshinylittlepassword" PASSWD2 = "myshinylittlepassword2" PASSWD3 = "myshinylittlepassword3" +def have_luks2(): + try: + succ = BlockDev.utils_check_util_version("cryptsetup", "2.0.0", "--version", r"cryptsetup ([0-9+\.]+)") + except GLib.GError: + return False + else: + return succ + +HAVE_LUKS2 = have_luks2() + + class CryptoTestCase(unittest.TestCase): requested_plugins = BlockDev.plugin_specs_from_names(("crypto",)) @@ -68,6 +79,27 @@ os.unlink(self.keyfile) + def _luks_format(self, device, passphrase, keyfile): + return BlockDev.crypto_luks_format(device, None, 0, passphrase, keyfile, 0) + + def _luks2_format(self, device, passphrase, keyfile): + # we currently don't support creating luks2 format using libblockdev + succ = True + if passphrase is not None: + ret, _out, _err = run_command("echo -n '%s' | cryptsetup luksFormat --type=luks2 %s -" % (PASSWD, device)) + succ = ret == 0 + + if keyfile is not None: + ret, _out, _err = run_command("echo -n '%s' | cryptsetup luksAddKey %s %s -" % (PASSWD, device, keyfile)) + succ = (succ and ret == 0) + else: + if keyfile is None: + raise RuntimeError("At least one of 'passphrase' and 'keyfile' must be specified.") + ret, _out, _err = run_command("cryptsetup luksFormat --type=luks2 --keyfile=%s %s -" % (keyfile, device)) + succ = ret == 0 + + return succ + class CryptoTestGenerateBackupPassphrase(CryptoTestCase): def setUp(self): # we don't need block devices for this test @@ -103,12 +135,11 @@ self.assertTrue(succ) class CryptoTestResize(CryptoTestCase): - @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_resize(self): + def _resize(self, create_fn): """Verify that resizing LUKS device works""" # the simple case with password - succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-cbc-essiv:sha256", 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) succ = BlockDev.crypto_luks_open(self.loop_dev, "libblockdevTestLUKS", PASSWD, None, False) @@ -125,12 +156,15 @@ succ = BlockDev.crypto_luks_close("libblockdevTestLUKS") self.assertTrue(succ) -class CryptoTestOpenClose(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_luks_open_close(self): + def test_luks_resize(self): + self._resize(self._luks_format) + +class CryptoTestOpenClose(CryptoTestCase): + def _luks_open_close(self, create_fn): """Verify that opening/closing LUKS device works""" - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, self.keyfile, 0) + succ = create_fn(self.loop_dev, PASSWD, self.keyfile) self.assertTrue(succ) with self.assertRaises(GLib.GError): @@ -159,12 +193,20 @@ succ = BlockDev.crypto_luks_close("libblockdevTestLUKS") self.assertTrue(succ) -class CryptoTestAddKey(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_add_key(self): + def test_luks_open_close(self): + self._luks_open_close(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_open_close(self): + self._luks_open_close(self._luks2_format) + +class CryptoTestAddKey(CryptoTestCase): + def _add_key(self, create_fn): """Verify that adding key to LUKS device works""" - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) with self.assertRaises(GLib.GError): @@ -176,12 +218,20 @@ succ = BlockDev.crypto_luks_add_key_blob(self.loop_dev, [ord(c) for c in PASSWD2], [ord(c) for c in PASSWD3]) self.assertTrue(succ) -class CryptoTestRemoveKey(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_remove_key(self): + def test_luks_add_key(self): + self._add_key(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_add_key(self): + self._add_key(self._luks2_format) + +class CryptoTestRemoveKey(CryptoTestCase): + def _remove_key(self, create_fn): """Verify that removing key from LUKS device works""" - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) succ = BlockDev.crypto_luks_add_key(self.loop_dev, PASSWD, None, PASSWD2, None) @@ -199,6 +249,15 @@ succ = BlockDev.crypto_luks_remove_key_blob(self.loop_dev, [ord(c) for c in PASSWD2]) self.assertTrue(succ) + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + def test_luks_remove_key(self): + self._remove_key(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_remove_key(self): + self._remove_key(self._luks2_format) + class CryptoTestErrorLocale(CryptoTestCase): def setUp(self): self._orig_loc = None @@ -225,11 +284,10 @@ self.assertIn("Operation not permitted", str(e)) class CryptoTestChangeKey(CryptoTestCase): - @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_change_key(self): + def _change_key(self, create_fn): """Verify that changing key in LUKS device works""" - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) succ = BlockDev.crypto_luks_change_key(self.loop_dev, PASSWD, PASSWD2) @@ -238,15 +296,23 @@ succ = BlockDev.crypto_luks_change_key_blob(self.loop_dev, [ord(c) for c in PASSWD2], [ord(c) for c in PASSWD3]) self.assertTrue(succ) -class CryptoTestIsLuks(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_is_luks(self): + def test_luks_change_key(self): + self._change_key(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_change_key(self): + self._change_key(self._luks2_format) + +class CryptoTestIsLuks(CryptoTestCase): + def _is_luks(self, create_fn): """Verify that LUKS device recognition works""" with self.assertRaises(GLib.GError): BlockDev.crypto_device_is_luks("/non/existing/device") - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) is_luks = BlockDev.crypto_device_is_luks(self.loop_dev) @@ -255,15 +321,23 @@ is_luks = BlockDev.crypto_device_is_luks(self.loop_dev2) self.assertFalse(is_luks) -class CryptoTestLuksStatus(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_luks_status(self): + def test_is_luks(self): + self._is_luks(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_is_luks2(self): + self._is_luks(self._luks2_format) + +class CryptoTestLuksStatus(CryptoTestCase): + def _luks_status(self, create_fn): """Verify that LUKS device status reporting works""" with self.assertRaises(GLib.GError): BlockDev.crypto_luks_status("/non/existing/device") - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) succ = BlockDev.crypto_luks_open(self.loop_dev, "libblockdevTestLUKS", PASSWD, None, False) @@ -283,12 +357,20 @@ with self.assertRaises(GLib.GError): BlockDev.crypto_luks_status("libblockdevTestLUKS") -class CryptoTestGetUUID(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_get_uuid(self): + def test_luks_status(self): + self._luks_status(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_status(self): + self._luks_status(self._luks2_format) + +class CryptoTestGetUUID(CryptoTestCase): + def _get_uuid(self, create_fn): """Verify that getting LUKS device UUID works""" - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) uuid = BlockDev.crypto_luks_uuid(self.loop_dev) @@ -297,12 +379,20 @@ with self.assertRaises(GLib.GError): uuid = BlockDev.crypto_luks_uuid(self.loop_dev2) -class CryptoTestLuksOpenRW(CryptoTestCase): @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") - def test_luks_open_rw(self): + def test_luks_get_uuid(self): + self._get_uuid(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_get_uuid(self): + self._get_uuid(self._luks2_format) + +class CryptoTestLuksOpenRW(CryptoTestCase): + def _luks_open_rw(self, create_fn): """Verify that a LUKS device can be activated as RW as well as RO""" - succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0) + succ = create_fn(self.loop_dev, PASSWD, None) self.assertTrue(succ) succ = BlockDev.crypto_luks_open(self.loop_dev, "libblockdevTestLUKS", PASSWD, None, False) @@ -326,6 +416,14 @@ succ = BlockDev.crypto_luks_close("libblockdevTestLUKS") self.assertTrue(succ) + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + def test_luks_open_rw(self): + self._luks_open_rw(self._luks_format) + + @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests") + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_open_rw(self): + self._luks_open_rw(self._luks2_format) class CryptoTestEscrow(CryptoTestCase): def setUp(self): diff -Nru libblockdev-2.14/tests/fs_test.py libblockdev-2.16/tests/fs_test.py --- libblockdev-2.14/tests/fs_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/fs_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -5,7 +5,7 @@ import tempfile from contextlib import contextmanager import utils -from utils import run, create_sparse_tempfile, mount, umount +from utils import run, create_sparse_tempfile, mount, umount, unstable_test import six import overrides_hack @@ -35,11 +35,12 @@ @classmethod def setUpClass(cls): + BlockDev.switch_init_checks(False) if not BlockDev.is_initialized(): BlockDev.init(cls.requested_plugins, None) else: BlockDev.reinit(cls.requested_plugins, True, None) - + BlockDev.switch_init_checks(True) try: cls.ntfs_avail = BlockDev.fs_is_tech_avail(BlockDev.FSTech.NTFS, BlockDev.FSTechMode.MKFS | @@ -1125,6 +1126,8 @@ self.assertTrue(os.path.ismount(tmp)) class GenericCheck(FSTestCase): + log = [] + def _test_generic_check(self, mkfs_function): # clean the device succ = BlockDev.fs_clean(self.loop_dev) @@ -1132,14 +1135,36 @@ succ = mkfs_function(self.loop_dev, None) self.assertTrue(succ) + self.log = [] # check for consistency (expected to be ok) succ = BlockDev.fs_check(self.loop_dev) self.assertTrue(succ) + def _my_progress_func(self, task, status, completion, msg): + self.assertTrue(isinstance(completion, int)) + self.log.append(completion) + + def _verify_progress(self, log): + # at least 2 members + self.assertLessEqual(2, len(log)) + # non-decreasing members + self.assertTrue(all(x<=y for x, y in zip(log, log[1:]))) + def test_ext4_generic_check(self): """Test generic check function with an ext4 file system""" self._test_generic_check(mkfs_function=BlockDev.fs_ext4_mkfs) + def test_ext4_progress_check(self): + """Test check function with an ext4 file system and progress reporting""" + + succ = BlockDev.utils_init_prog_reporting(self._my_progress_func) + self.assertTrue(succ) + + self._test_generic_check(mkfs_function=BlockDev.fs_ext4_mkfs) + self._verify_progress(self.log) + + succ = BlockDev.utils_init_prog_reporting(None) + def test_xfs_generic_check(self): """Test generic check function with an ext4 file system""" self._test_generic_check(mkfs_function=BlockDev.fs_xfs_mkfs) @@ -1264,6 +1289,7 @@ fs_info_func=info_prepare, info_size_func=expected_size) + @unstable_test def test_vfat_generic_resize(self): """Test generic resize function with a vfat file system""" self._test_generic_resize(mkfs_function=BlockDev.fs_vfat_mkfs) diff -Nru libblockdev-2.14/tests/kbd_test.py libblockdev-2.16/tests/kbd_test.py --- libblockdev-2.14/tests/kbd_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/kbd_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -4,7 +4,7 @@ import time from contextlib import contextmanager from distutils.version import LooseVersion -from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, wipe_all, fake_path, read_file, skip_on +from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, wipe_all, fake_path, read_file, skip_on, unstable_test from bytesize import bytesize import overrides_hack @@ -332,6 +332,7 @@ class KbdTestBcacheCreate(KbdBcacheTestCase): @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_create_destroy(self): """Verify that it's possible to create and destroy a bcache device""" @@ -350,6 +351,7 @@ wipe_all(self.loop_dev, self.loop_dev2) @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_create_destroy_full_path(self): """Verify that it's possible to create and destroy a bcache device with full device path""" @@ -369,6 +371,7 @@ class KbdTestBcacheAttachDetach(KbdBcacheTestCase): @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_attach_detach(self): """Verify that it's possible to detach/attach a cache from/to a bcache device""" @@ -394,6 +397,7 @@ wipe_all(self.loop_dev, self.loop_dev2) @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_attach_detach_full_path(self): """Verify that it's possible to detach/attach a cache from/to a bcache device with full device path""" @@ -419,6 +423,7 @@ wipe_all(self.loop_dev, self.loop_dev2) @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_detach_destroy(self): """Verify that it's possible to destroy a bcache device with no cache attached""" @@ -442,6 +447,7 @@ class KbdTestBcacheGetSetMode(KbdBcacheTestCase): @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_get_set_mode(self): """Verify that it is possible to get and set Bcache mode""" @@ -498,6 +504,7 @@ return sum(int(read_file(os.path.realpath(c) + '/../size')) for c in caches) @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_status(self): succ, dev = BlockDev.kbd_bcache_create(self.loop_dev, self.loop_dev2, None) self.assertTrue(succ) @@ -530,6 +537,7 @@ class KbdTestBcacheBackingCacheDevTest(KbdBcacheTestCase): @skip_on(("centos", "enterprise_linux")) + @unstable_test def test_bcache_backing_cache_dev(self): """Verify that is is possible to get the backing and cache devices for a Bcache""" diff -Nru libblockdev-2.14/tests/library_test.py libblockdev-2.16/tests/library_test.py --- libblockdev-2.14/tests/library_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/library_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -10,10 +10,10 @@ class LibraryOpsTestCase(unittest.TestCase): log = "" - # all plugins expcept mpath -- it doesn't have all the dependencies on Debian - # and we don't need it for this test - requested_plugins = BlockDev.plugin_specs_from_names(("btrfs", "crypto", "dm", - "fs", "kbd", "loop", "lvm", + # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all + # the dependencies on CentOS/Debian and we don't need them for this test + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", + "kbd", "loop", "lvm", "mdraid", "part", "swap")) @classmethod @@ -281,10 +281,10 @@ """Verify that loading only required plugins works as expected""" ps = BlockDev.PluginSpec() - ps.name = BlockDev.Plugin.BTRFS + ps.name = BlockDev.Plugin.SWAP ps.so_name = "" self.assertTrue(BlockDev.reinit([ps], True, None)) - self.assertEqual(BlockDev.get_available_plugin_names(), ["btrfs"]) + self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) def test_not_implemented(self): @@ -294,10 +294,10 @@ self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) ps = BlockDev.PluginSpec() - ps.name = BlockDev.Plugin.BTRFS + ps.name = BlockDev.Plugin.SWAP ps.so_name = "" self.assertTrue(BlockDev.reinit([ps], True, None)) - self.assertEqual(BlockDev.get_available_plugin_names(), ["btrfs"]) + self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) # no longer loaded with self.assertRaises(GLib.GError): @@ -317,18 +317,18 @@ self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) # reinit with a subset of plugins - plugins = BlockDev.plugin_specs_from_names(["btrfs", "lvm"]) + plugins = BlockDev.plugin_specs_from_names(["swap", "lvm"]) self.assertTrue(BlockDev.reinit(plugins, True, None)) - self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["btrfs", "lvm"])) + self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) # ensure_init with the same subset -> nothing should change self.assertTrue(BlockDev.ensure_init(plugins, None)) - self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["btrfs", "lvm"])) + self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) # ensure_init with more plugins -> extra plugins should be loaded - plugins = BlockDev.plugin_specs_from_names(["btrfs", "lvm", "crypto"]) + plugins = BlockDev.plugin_specs_from_names(["swap", "lvm", "crypto"]) self.assertTrue(BlockDev.ensure_init(plugins, None)) - self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["btrfs", "lvm", "crypto"])) + self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm", "crypto"])) # reinit to unload all plugins self.assertTrue(BlockDev.reinit([], True, None)) @@ -336,7 +336,7 @@ # ensure_init to load all plugins back self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) - self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 9) + self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 8) def test_try_reinit(self): """Verify that try_reinit() works as expected""" @@ -344,22 +344,22 @@ # try reinitializing with only some utilities being available and thus # only some plugins able to load with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", - "btrfs", "thin_metadata_size", "swaplabel"]): + "thin_metadata_size", "swaplabel"]): succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) self.assertFalse(succ) - for plug_name in ("swap", "lvm", "btrfs"): + for plug_name in ("swap", "lvm", "crypto"): self.assertIn(plug_name, loaded) # reset back to all plugins self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) # now the same with a subset of plugins requested - plugins = BlockDev.plugin_specs_from_names(["btrfs", "lvm", "swap"]) - with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "btrfs", + plugins = BlockDev.plugin_specs_from_names(["lvm", "swap", "crypto"]) + with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "thin_metadata_size", "swaplabel"]): succ, loaded = BlockDev.try_reinit(plugins, True, None) self.assertTrue(succ) - self.assertEqual(set(loaded), set(["swap", "lvm", "btrfs"])) + self.assertEqual(set(loaded), set(["swap", "lvm", "crypto"])) def test_non_en_init(self): """Verify that the library initializes with lang different from en_US""" diff -Nru libblockdev-2.14/tests/overrides_test.py libblockdev-2.16/tests/overrides_test.py --- libblockdev-2.14/tests/overrides_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/overrides_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -5,10 +5,10 @@ class OverridesTest(unittest.TestCase): - # all plugins expcept mpath -- it doesn't have all the dependencies on Debian - # and we don't need it for this test - requested_plugins = BlockDev.plugin_specs_from_names(("btrfs", "crypto", "dm", - "fs", "kbd", "loop", "lvm", + # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all + # the dependencies on CentOS/Debian and we don't need them for this test + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", + "kbd", "loop", "lvm", "mdraid", "part", "swap")) @classmethod diff -Nru libblockdev-2.14/tests/part_test.py libblockdev-2.16/tests/part_test.py --- libblockdev-2.14/tests/part_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/part_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -1370,3 +1370,31 @@ # we can't change part id to extended partition id with self.assertRaises(GLib.GError): BlockDev.part_set_part_id (self.loop_dev, ps.path, "0x85") + + +class PartSetGptFlagsCase(PartTestCase): + def test_set_part_type(self): + """Verify that it is possible to set and get partition flags on GPT""" + + esp_guid = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" + + # we first need a GPT partition table + succ = BlockDev.part_create_table (self.loop_dev, BlockDev.PartTableType.GPT, True) + self.assertTrue(succ) + + # for now, let's just create a typical primary partition starting at the + # sector 2048, 10 MiB big with optimal alignment + ps = BlockDev.part_create_part (self.loop_dev, BlockDev.PartTypeReq.NORMAL, 2048*512, 10 * 1024**2, BlockDev.PartAlign.OPTIMAL) + + # set GUID (part type) to check that changing flags doesn't change it + succ = BlockDev.part_set_part_type (self.loop_dev, ps.path, esp_guid) + self.assertTrue(succ) + ps = BlockDev.part_get_part_spec (self.loop_dev, ps.path) + self.assertEqual(ps.type_guid, esp_guid) + + # set LEGACY_BOOT flag and test it + succ = BlockDev.part_set_part_flags (self.loop_dev, ps.path, BlockDev.PartFlag.LEGACY_BOOT) + self.assertTrue(succ) + ps = BlockDev.part_get_part_spec (self.loop_dev, ps.path) + self.assertTrue(ps.flags & BlockDev.PartFlag.LEGACY_BOOT) + self.assertEqual(ps.type_guid, esp_guid) diff -Nru libblockdev-2.14/tests/README.rst libblockdev-2.16/tests/README.rst --- libblockdev-2.14/tests/README.rst 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/README.rst 2018-02-08 11:10:41.000000000 +0000 @@ -1,2 +1,2 @@ See the chapter `Testing libblockdev' in the docs/ directory or on-line at -http://rhinstaller.github.io/libblockdev/ +http://storaged.org/libblockdev/ diff -Nru libblockdev-2.14/tests/run_tests.py libblockdev-2.16/tests/run_tests.py --- libblockdev-2.14/tests/run_tests.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/run_tests.py 2018-02-08 11:10:41.000000000 +0000 @@ -10,7 +10,9 @@ import sys import unittest -LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/lib/.libs' +from distutils.spawn import find_executable + +LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs' GIDIR = 'src/lib' @@ -73,8 +75,9 @@ result = unittest.TextTestRunner(verbosity=2, failfast=args.stop).run(suite) # dump cropped journal to log file - with open('journaldump.log', 'w') as outfile: - subprocess.call(['journalctl', '-S', start_time], stdout=outfile) + if find_executable('journalctl'): + with open('journaldump.log', 'w') as outfile: + subprocess.call(['journalctl', '-S', start_time], stdout=outfile) if result.wasSuccessful(): sys.exit(0) diff -Nru libblockdev-2.14/tests/utils.py libblockdev-2.16/tests/utils.py --- libblockdev-2.14/tests/utils.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/utils.py 2018-02-08 11:10:41.000000000 +0000 @@ -1,3 +1,5 @@ +from __future__ import print_function + import os import re import glob @@ -6,6 +8,7 @@ import dbus import unittest import time +import sys from contextlib import contextmanager from itertools import chain @@ -214,11 +217,11 @@ with open(filename, "w") as f: f.write(content) -def run_command(command): +def run_command(command, cmd_input=None): res = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stderr=subprocess.PIPE, stdin=subprocess.PIPE) - out, err = res.communicate() + out, err = res.communicate(input=cmd_input) return (res.returncode, out.decode().strip(), err.decode().strip()) def get_version_from_pretty_name(pretty_name): @@ -315,6 +318,30 @@ return decorator +# taken from udisks2/src/tests/dbus-tests/udiskstestcase.py +def unstable_test(test): + """Decorator for unstable tests + + Failures of tests decorated with this decorator are silently ignored unless + the ``UNSTABLE_TESTS_FATAL`` environment variable is defined. + """ + + def decorated_test(*args): + try: + test(*args) + except unittest.SkipTest: + # make sure skipped tests are just skipped as usual + raise + except: + # and swallow everything else, just report a failure of an unstable + # test, unless told otherwise + if "UNSTABLE_TESTS_FATAL" in os.environ: + raise + print("unstable-fail...", end="", file=sys.stderr) + + return decorated_test + + def run(cmd_string): """ Run the a command with file descriptors closed as lvm is trying to diff -Nru libblockdev-2.14/tests/utils_test.py libblockdev-2.16/tests/utils_test.py --- libblockdev-2.14/tests/utils_test.py 2017-10-31 09:46:57.000000000 +0000 +++ libblockdev-2.16/tests/utils_test.py 2018-02-08 11:10:41.000000000 +0000 @@ -18,6 +18,32 @@ else: BlockDev.reinit(cls.requested_plugins, True, None) +class UtilsExecProgressTest(UtilsTestCase): + log = [] + + def my_progress_func(self, task, status, completion, msg): + self.assertTrue(isinstance(completion, int)) + self.log.append(completion) + + def test_initialization(self): + """ Verify that progress report can (de)initialized""" + + succ = BlockDev.utils_prog_reporting_initialized() + self.assertFalse(succ) + + succ = BlockDev.utils_init_prog_reporting(self.my_progress_func) + self.assertTrue(succ) + + succ = BlockDev.utils_prog_reporting_initialized() + self.assertTrue(succ) + + succ = BlockDev.utils_init_prog_reporting(None) + self.assertTrue(succ) + + succ = BlockDev.utils_prog_reporting_initialized() + self.assertFalse(succ) + + class UtilsExecLoggingTest(UtilsTestCase): log = ""