Compare commits

...

154 Commits

Author SHA1 Message Date
Andrius Štikonas 83a865411d ExternalCommandHelper::ReadData should not follow symlinks.
Resolve all symlinks in the userspace application and make sure
that helper only deals with root owned path in /dev but not in
/dev/shm.
2022-06-20 00:03:18 +01:00
A. Wilcox 26e069d6cd
Tests: Fix backend loading for tests
Using $<TARGET_FILE> we receive the entire plugin file path, leading to
errors such as:

kf.coreaddons: no metadata found in "kpmcore//home/awilcox/Code/KDE/kpmcore/bin/kpmcore/pmdummybackendplugin.so" "The shared library was not found."

Using $<TARGET_FILE_NAME> instead we are able to have just the plugin
name, which does load properly.  The tests now pass.
2022-06-12 16:14:51 -05:00
l10n daemon script eb50358b72 GIT_SILENT made messages (after extraction) 2022-06-09 01:01:02 +00:00
ivan tkachenko 9b015661aa
Present SMART status duration in more human-readable spellout format
BUG: 449386
2022-05-29 16:56:27 +03:00
Andrius Štikonas fd4a330887 Allow setting empty FAT label.
This breaks compatibility with dosfstools 4.1

BUG: 453388
2022-05-15 23:20:25 +01:00
l10n daemon script 6204041935 GIT_SILENT made messages (after extraction) 2022-05-15 00:54:27 +00:00
Andrius Štikonas 36881cde62 Fix location of GPT header on 4K LBA devices.
BUG: 453333
2022-05-04 17:49:08 +01:00
l10n daemon script d247e027a1 GIT_SILENT made messages (after extraction) 2022-03-29 00:58:46 +00:00
Andrius Štikonas 5afe143a19 Add a maximum file size limit when writing to /etc/fstab file. 2022-03-27 14:19:56 +01:00
Andrius Štikonas c9d7e0cd6e Fix path to reuse-lint yaml file. 2022-03-21 18:54:53 +00:00
Andrius Štikonas 7c299857c8 Add reuse lint. 2022-03-21 18:54:01 +00:00
Andrius Štikonas 0c1af38e5e Use lowercase for cmake functions. 2022-03-20 21:10:17 +00:00
Andrius Štikonas 6b260fa84e Only run partitioning commands from trusted prefixes. 2022-03-20 21:07:17 +00:00
l10n daemon script e112ebe944 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-03-20 02:14:59 +00:00
l10n daemon script 05a96c874f GIT_SILENT made messages (after extraction) 2022-03-20 00:55:56 +00:00
Albert Astals Cid 76ede03bd2 GIT_SILENT Upgrade release service version to 22.07.70. 2022-03-12 13:26:33 +01:00
l10n daemon script bbcfd8202b GIT_SILENT made messages (after extraction) 2022-03-05 00:47:19 +00:00
l10n daemon script 1006a8daeb SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-02-27 01:56:05 +00:00
l10n daemon script b6a52fe2b1 GIT_SILENT made messages (after extraction) 2022-02-27 00:52:28 +00:00
l10n daemon script 0681ebd790 GIT_SILENT made messages (after extraction) 2022-02-21 00:47:25 +00:00
Andrius Štikonas 858f8d9bae Add a comment about WriteOnly. 2022-02-20 20:49:57 +00:00
Andrius Štikonas d92ebc0b76 Rename variables into more appropriate fstabPath and fstabFile. 2022-02-20 20:47:43 +00:00
Andrius Štikonas e483bab0d5 Restrict CreateFile method to WriteFstab method in polkit helper. 2022-02-20 19:42:25 +00:00
Andrius Štikonas 27b85117c4 Rename blockSize to chunkSize to avoid confusion with physical blocks. 2022-02-20 14:41:31 +00:00
Andrius Štikonas d9ceb50238 Add a few more comments explaining copy direction. 2022-02-20 14:41:31 +00:00
l10n daemon script 237d246457 GIT_SILENT made messages (after extraction) 2022-02-20 00:48:23 +00:00
Laurent Montel 8a209e9616 Fix building against qt6 we need kf5.90 2022-02-18 07:22:57 +01:00
l10n daemon script 3f1949f477 GIT_SILENT made messages (after extraction) 2022-02-18 00:48:05 +00:00
Andrius Štikonas c05bb54bc5 Set "false" as the default return value and change it to "true" on success.
Please enter the commit message for your changes. Lines starting
2022-02-15 19:56:46 +00:00
Andrius Štikonas fb1708b958 Fix a typo in definition of MiB constant. 2022-02-15 19:14:19 +00:00
l10n daemon script 94c1ff7133 GIT_SILENT made messages (after extraction) 2022-02-13 00:46:08 +00:00
l10n daemon script b4f5faed58 GIT_SILENT made messages (after extraction) 2022-02-12 00:46:25 +00:00
l10n daemon script 49900e80bf GIT_SILENT made messages (after extraction) 2022-02-11 00:47:29 +00:00
l10n daemon script e0d6c1ce43 GIT_SILENT made messages (after extraction) 2022-02-10 00:46:44 +00:00
l10n daemon script cff0f16a7d GIT_SILENT made messages (after extraction) 2022-02-09 00:50:22 +00:00
Andrius Štikonas 5717c3aa0b Update description of polkit helper. 2022-02-08 21:39:18 +00:00
Andrius Štikonas 1c87b494ef Add a node for Qt6. 2022-02-06 21:18:29 +00:00
Andrius Štikonas fd7f9b87a9 Do not repeatedly open and close file when reading from it. 2022-02-06 21:18:29 +00:00
Andrius Štikonas eddbd7a301 Do not repeatedly open and close file when writing to it. 2022-02-06 21:06:39 +00:00
Andrius Štikonas fb11a02d24 It is no longer necessary to namespace exit function. 2022-02-06 01:27:09 +00:00
Andrius Štikonas 4ef17463ff Make sure that path passed to WriteData is block device. 2022-02-05 14:42:17 +00:00
Andrius Štikonas 81a5eae665 Restrict CopyFileData to writing to already existing files. 2022-02-05 14:12:38 +00:00
Andrius Štikonas 3903ae1b83 Rename CopyBlocks to CopyFileData. 2022-02-05 14:05:50 +00:00
Andrius Štikonas 949ce01ae4 Check for relative paths in ExternalCommandHelper::CopyBlocks. 2022-02-05 13:48:37 +00:00
Andrius Štikonas 5d1c03b9d8 Restrict QProcess::ProcessChannelMode to two used values.
Casting and passing the processChannel argument unfiltered to QProcess
could pose a security issue if future additions are made to
QProcess that introduce new behaviour.
2022-02-05 13:24:38 +00:00
Andrius Štikonas 1502494eda Be a bit more strict in root helper when checking path to /etc/fstab. 2022-02-05 13:13:12 +00:00
Andrius Štikonas e2f097fce8 Remove unnecessary or non-existing Qt flags. 2022-01-21 00:29:01 +00:00
Andrius Štikonas 04170918bc Set KDE_COMPILERSETTINGS_LEVEL to 5.85. 2022-01-20 22:31:06 +00:00
Andrius Štikonas c6e37dbd8e One more missed place with INCLUDE_INSTALL_DIR. 2022-01-20 19:13:02 +00:00
Andrius Štikonas deb82fe2f9 Also remove INCLUDE_INSTALL_DIR in KPMcoreConfig.cmake file. 2022-01-20 19:10:58 +00:00
Andrius Štikonas 19cda738bd Do not set INCLUDE_INSTALL_DIR variable. 2022-01-20 19:04:53 +00:00
Andrius Štikonas cbea744bb3 Fix obsolete ECM variables 2022-01-20 18:35:33 +00:00
Andrius Štikonas a69bbb559d Fix cmake config file template to work with Qt6. 2022-01-18 01:18:04 +00:00
Andrius Štikonas 72b4142bcb Fix infinite recursion in dummy backend.
BUG: 432704
2022-01-16 14:22:50 +00:00
Andrius Štikonas 5174dce64f Remove unused forward declaration. 2022-01-16 13:59:01 +00:00
Andrius Štikonas 67550ca2f7 Add Qt6 CI. 2022-01-16 00:21:21 +00:00
Andrius Štikonas 73de1709e2 Port to Qt6. 2022-01-16 00:17:46 +00:00
Andrius Štikonas 08d2e3dc2c Changing swap labels while swap is active does not seem to work anymore. 2022-01-15 23:14:49 +00:00
Andrius Štikonas 7eb2ceed17 Port QStringRef to QStringView. 2022-01-15 22:49:42 +00:00
Andrius Štikonas b0cd5def42 Remove unused variable. 2022-01-15 22:33:29 +00:00
Andrius Štikonas d7912e21d8 Port away from KPluginLoader::factory. 2022-01-10 01:16:20 +00:00
Andrius Štikonas c31eabc842 Port away from deprecated method. 2022-01-10 01:11:13 +00:00
Andrius Štikonas 1d7a4e4010 Port away from KPluginLoader::metaData. 2022-01-10 00:33:43 +00:00
Andrius Štikonas 30d428c697 Port away from KPluginMetaData::serviceTypes. 2022-01-10 00:24:53 +00:00
Andrius Štikonas 5ffc5c6f23 Fix davfs entries being omitted from fstab file.
BUG: 447961
2022-01-05 23:00:17 +00:00
Andrius Štikonas e58ab02bac Add support for copying unknown partitions.
BUG: 447784
2022-01-01 16:18:57 +00:00
Andrius Štikonas d2fb56bcd2 Allow running chmod in externalcommand helper. 2021-12-28 15:26:01 +00:00
Tomaz Canabrava 770e16eb02 Use --recursive instead of -r 2021-12-28 15:07:35 +00:00
Tomaz Canabrava 36bb57c0dd Add posix permissions on filesystems used in posix systems 2021-12-28 15:07:35 +00:00
Tomaz Canabrava e1774d4026 Remove unused member 2021-12-28 15:07:35 +00:00
Tomaz Canabrava 9093b27bd8 Move the changePosixPermission to the Filesystem
And implement it on ext2, 3, 4. I don't know all the filesystems
that can have posix permissions, those three will do. if we need
more in the future we implement them, it's two lines of code.
2021-12-28 15:07:35 +00:00
Tomaz Canabrava 6c14ddb043 Add new job to change permission of the newly created partition 2021-12-28 15:07:35 +00:00
Andrius Štikonas 68c8fecffd Simplify code using K_PLUGIN_CLASS_WITH_JSON macro.
Also move kpmcore plugins into separate namespace.
2021-12-24 18:58:41 +00:00
Andrius Štikonas a5bdd5a4eb Switch to ntfsinfo to read NTFS usage.
BUG: 447248
2021-12-24 00:03:05 +00:00
Andrius Štikonas 31921c59fa Fix broken fstab when mount point includes space.
fstab column width was calculated before spaces were escaped which would
result in no space between mount point and file system type columns.

BUG: 446218
2021-12-04 23:31:02 +00:00
Tomaz Canabrava 65f986dc29 Add method to query if polkit is installed correctly
The std::cout and qDebugs on the external command helper is
not visible to the user as it runs in another process via dbus
this is highly annoying if you want to be able to discover what's
wrong on the command line.

A method that checks if the file is in the right place should be
called by the users of this library
2021-11-29 11:16:33 -03:00
Albert Astals Cid 259f562698 Add CI 2021-11-28 12:55:05 +01:00
Harald Sitter c79f5831ff add metainfo file
requirement to get generated on api.kde.org
2021-11-24 10:31:41 +00:00
Harald Sitter b3d0cfccaf set cmake interface dir on the target
this carries through into the Targets.cmake file we install which in
turn means that the imported target for the consumer defines its include
directory. this removes the need to manually add the include dir

also updated the readme accordingly
2021-11-23 10:14:58 +01:00
Ben Cooksley d9339e4833 Add additional dependencies of KPMCore 2021-11-21 16:40:25 +13:00
Ben Cooksley 702b30ee3a Add CI definitions for the seed job 2021-11-21 16:24:08 +13:00
l10n daemon script 172b76fe9b GIT_SILENT made messages (after extraction) 2021-11-20 00:30:09 +00:00
Andrius Štikonas e9fc875c5e Fix seek error when filling device with random data or zeroes. 2021-11-12 01:02:34 +00:00
l10n daemon script a9998425fd SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-11-09 01:23:12 +00:00
l10n daemon script 74218e12d6 GIT_SILENT made messages (after extraction) 2021-11-09 00:19:35 +00:00
Heiko Becker 644db18c75 GIT_SILENT Upgrade release service version to 22.03.70. 2021-11-08 20:59:42 +01:00
Andrius Štikonas 282cfdcde1 Do not destroy zfs pool when removing zfs partition.
This can be dangerous, e.g. if partition is part of raid set.
So better be more cautious and in some cases fail to remove partition
than lose data.
2021-10-30 21:13:09 +01:00
Andrius Štikonas 6f2be13f68 Bump minimal cmake version to 3.16 2021-09-29 17:56:45 +01:00
l10n daemon script 2734c58069 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-09-08 01:30:14 +00:00
l10n daemon script d31f1733b6 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-09-06 01:28:56 +00:00
Artem Grinev 00e6b77c29 Initialize all fields in Partition 2021-08-29 00:16:57 +04:00
Artem Grinev f4664671d6 Clear attributes on new partition creation 2021-08-27 02:37:19 +04:00
Albert Astals Cid c47ee6cae7 GIT_SILENT Upgrade release service version to 21.11.70. 2021-07-10 20:29:09 +02:00
l10n daemon script 4c32c38655 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-07-08 01:22:49 +00:00
l10n daemon script b3050dc894 GIT_SILENT made messages (after extraction) 2021-07-08 00:20:41 +00:00
l10n daemon script f0188249e8 GIT_SILENT made messages (after extraction) 2021-05-17 00:27:08 +00:00
l10n daemon script ce39e14904 GIT_SILENT made messages (after extraction) 2021-03-27 02:33:43 +01:00
Yaroslav Sidlovsky 8746ef72fd Fix smartctl exit status success check
According to the smartctl man page:
```
EXIT STATUS
The  exit  statuses of smartctl are defined by a bitmask.  If all is well with the disk, the exit status (return value) of smartctl is 0 (all bits turned off).  If a problem occurs, or an error, potential error, or fault is detected, then a non-zero status is
returned.  In this case, the eight different bits in the exit status have the following meanings for ATA disks; some of these values may also be returned for SCSI disks.

Bit 0: Command line did not parse.

Bit 1: Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode (see '-n' option above).

Bit 2: Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure (see '-b' option above).

Bit 3: SMART status check returned "DISK FAILING".

Bit 4: We found prefail Attributes <= threshold.

Bit 5: SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past.

Bit 6: The device error log contains records of errors.

Bit 7: The device self-test log contains records of errors.  [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored.
```

BUG: 429028
2021-03-17 16:03:32 +03:00
Albert Astals Cid ad35460628 GIT_SILENT Upgrade release service version to 21.07.70. 2021-03-13 22:28:27 +01:00
l10n daemon script c06a188d0e GIT_SILENT made messages (after extraction) 2021-03-03 03:33:29 +01:00
Guillaume Girol 0094461f60 lvm without arguments has returncode 3 2021-02-27 12:00:00 +00:00
Andrius Štikonas ad888767bb Use QStringLiteral. 2021-02-23 21:39:41 +00:00
Oxalica -- eea84fb605 Fix out of bounds read when parsing fstab.
Some fstab files only have 3 fields and mount options are completely omitted.
2021-02-22 16:45:48 +00:00
Andrius Štikonas 36dfae351f Add initial support for dosfstools 4.2.
Empty labels are not allowed anymore.
One can reset them with -r flag but that is not supported in older
dosfstools. So for now we just manually set label to NO_LABEL.

BUG: 432941
2021-02-19 17:51:43 +00:00
Michael Weghorn 813e574001 Wipe existing signatures when creating partition table
As the sfdisk man page says on the option '--wipe' that
specifies whether or not to wipe signatures in order
to avoid collisions:

> When this option is not given, the default is auto,
> in which case signatures are wiped only when in interactive mode

but sfdisk is not run in interactive mode here, since
stdin does not refer to a terminal, and the sfdisk
man page says:

> It [i.e. sfdisk] runs in interactive mode if executed on terminal
> (stdin refers to a terminal).

Therefore, explicitly pass the '--wipe=always' option to
sfdisk so that old signatures are wiped when a new partition
table is created.

Bug: 431628
2021-01-15 09:53:20 +01:00
Andrius Štikonas 31706cffdc Fix out of bounds read when parsing fstab.
BUG: 429191
2021-01-07 01:25:12 +00:00
Andrius Štikonas 06f15334ec Add support for exfatprogs
Bug: 430907
2020-12-28 17:50:07 +00:00
l10n daemon script 338811601b GIT_SILENT made messages (after extraction) 2020-12-07 02:39:36 +01:00
Andrius Štikonas a06d4ba0f7 Return QByteArray instead of bool in readData. 2020-11-29 23:34:29 +00:00
Andrius Štikonas 73da1bc514 Only allow using ReadData on block devices. 2020-11-29 23:24:49 +00:00
Andrius Štikonas b0e5fa66c4 Add an explicit ReadData method to polkit helper instead of relying on copyblocks with empty target device. 2020-11-29 23:14:08 +00:00
Andrius Štikonas 502ebc0474 Remove declaration of non-existing method. 2020-11-29 22:42:19 +00:00
Andrius Štikonas 04a095a542 Simplify find syntax. 2020-11-29 13:49:50 +00:00
Andrius Štikonas 5da47c26e9 Replace array with unordered set for better performance. 2020-11-29 13:48:07 +00:00
Andrius Štikonas 551654de0d Also rename source/targetFirstByte ot offsets in function declarations. 2020-11-29 13:08:53 +00:00
Andrius Štikonas d34b617272 Rename source/targetFirstByte to source/targetOffset.
Add some diagrams explaining difference between
source/targetOffsets and read/writeOffset.
2020-11-29 01:54:48 +00:00
Andrius Štikonas ee0a1e1b41 Add a limit on the amount of data that can be passed back via DBus. 2020-11-29 01:08:43 +00:00
Andrius Štikonas c556f39064 Add a limit on blocksize to prevent out-of-memory situation. 2020-11-29 00:58:55 +00:00
Andrius Štikonas 9dd38744c5 Add a comment about auth_admin_keep. 2020-11-29 00:50:57 +00:00
Andrius Štikonas 4fa91d75f3 externalcommandhelper: Do not commit suicide when attempting to run non whitelisted command.
Simply returning failure should be sufficient.
2020-11-26 23:35:52 +00:00
Andrius Štikonas 32d146eed3 externalcommandhelper: Make copy direction an enum. 2020-11-26 23:26:31 +00:00
Andrius Štikonas d16d9e8019 Do not reuse QProcess object in externalcommandhelper for different invocations. 2020-11-26 22:05:25 +00:00
Andrius Štikonas fae9f83451 Fix division by zero. 2020-11-26 21:58:24 +00:00
Andrius Štikonas 4d3fcb7691 Merge branch 'release/20.12' 2020-11-17 11:25:44 +00:00
Friedrich W. H. Kossebau 6e8424bed6 Clean up include dirs
Move include of BLKID_INCLUDE_DIRS into scope it is used.
UUID_INCLUDE_DIRS is unused, left over from before partitionmanager
switched away from libuuid in 26e7f9d7ef306d61380e1c8965feb83bb6b07d18 .
Explicit Qt5Core_INCLUDE_DIRS no longer needed.
src/ is automatically available for kpmcore target, also exposed in
its build link interface.
2020-11-16 20:56:57 +00:00
Friedrich W. H. Kossebau 5413e696d3 Generate libpartitionmanagerexport.h 2020-11-16 20:56:57 +00:00
Friedrich W. H. Kossebau 2bf69932d1 testhelpers: link kpmcore to get the include directories from the interface 2020-11-16 20:56:57 +00:00
Friedrich W. H. Kossebau 32149e6340 CMake config file: check for Qt5Core in the needed version 2020-11-16 20:21:16 +01:00
Friedrich W. H. Kossebau 8804711943 Remove no longer existing include dir
NO_CHANGELOG
2020-11-16 17:25:44 +01:00
Andrius Štikonas 9d4ab0e6fd Merge branch 'release/20.12' 2020-11-16 16:18:14 +00:00
Friedrich W. H. Kossebau 07e5a3ac28 Make plugins compatible to latest KPluginFactory code
That one uses std::is_constructible<impl, QObject *, const QVariantList &>
which will fail for our current plugin constructors due to being private
and with only friend class KPluginFactory.
2020-11-16 17:14:52 +01:00
Andrius Štikonas 26acd7c10d Remove extra semicolon. 2020-11-14 01:09:23 +00:00
Andrius Štikonas 70d4819aae Merge branch 'release/20.12' 2020-11-14 01:04:31 +00:00
Andrius Štikonas 2e91730f7a Fix parsing fstab mountpoints when they contain spaces or tabs.
If the name of the mount point contains spaces or tabs these
can be escaped as `\040' and '\011' respectively.

BUG: 428932
2020-11-14 00:55:29 +00:00
Andrius Štikonas 2382b9e1c5 Rename d pointer to d_ptr to disambiguate from Device d. 2020-11-12 01:04:47 +00:00
Gaël PORTAY 2012e01b88 Bump soversion of kpmcore. 2020-11-11 16:41:16 -05:00
Gaël PORTAY 82566e63e7 d-pointerize NewOperation class. 2020-11-11 16:41:14 -05:00
Albert Astals Cid 0ee1e958a0 GIT_SILENT Upgrade release service version to 21.03.70. 2020-11-08 19:04:47 +01:00
Albert Astals Cid d1b2d9ba84 GIT_SILENT Upgrade release service version to 20.11.80. 2020-11-08 18:26:04 +01:00
l10n daemon script 495b1d7c45 GIT_SILENT made messages (after extraction) 2020-11-07 02:39:27 +01:00
l10n daemon script 6f89a9886b GIT_SILENT made messages (after extraction) 2020-11-05 02:41:29 +01:00
l10n daemon script a42fbfa5e4 GIT_SILENT made messages (after extraction) 2020-11-01 02:40:41 +01:00
l10n daemon script 5b8b8d2228 GIT_SILENT made messages (after extraction) 2020-10-29 02:50:01 +01:00
Andrius Štikonas 3448815596 kpmcore does not ship .ui or .rc files. 2020-10-28 11:12:27 +00:00
l10n daemon script b59f34aeb5 GIT_SILENT made messages (after extraction) 2020-10-28 02:43:18 +01:00
Andrius Štikonas 2c8d081357 reuse: Add SPDX info to src/util/org.kde.kpmcore.externalcommand.policy. 2020-10-27 12:20:34 +00:00
l10n daemon script 14777483a1 GIT_SILENT made messages (after extraction) 2020-10-27 02:40:51 +01:00
Andrius Štikonas 68fdf2fcf2 Use XmlMessages.sh for translations of polkit policy files. 2020-10-25 23:45:28 +00:00
Andrius Štikonas 19f78ef76a Port away from qAsConst. 2020-10-24 22:01:45 +01:00
Andrius Štikonas 7e8ae5b140 Require C++17 which was actually used already with enumerator attributes. 2020-10-24 16:34:12 +01:00
Andrius Štikonas 0c37cc54a6 Remove unnecessary semicolon (-Wpedantic). 2020-10-24 16:29:09 +01:00
Andrius Štikonas ec3479f302 Add overrides to destructors. 2020-10-24 01:33:52 +01:00
Andrius Štikonas 766105bb73 Switch to release service's versioning scheme. 2020-10-16 23:05:25 +01:00
Andrius Štikonas f51509e1bf Bump KF5 version requirement. 2020-10-16 21:37:17 +01:00
94 changed files with 1029 additions and 482 deletions

8
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/reuse-lint.yml

11
.kde-ci.yml Normal file
View File

@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
Dependencies:
- 'on': ['@all']
'require':
'frameworks/extra-cmake-modules': '@latest'
'frameworks/kcoreaddons': '@latest'
'frameworks/ki18n': '@latest'
'frameworks/kwidgetsaddons': '@latest'
'libraries/polkit-qt-1': '@latest'

View File

@ -18,7 +18,7 @@ Files: src/util/org.kde.kpmcore.helperinterface.conf
License: MIT
Copyright: 2018 Andrius Štikonas <andrius@stikonas.eu>
### KAuth actions
Files: src/util/org.kde.kpmcore.externalcommand.actions
# Just list of directories
Files: src/util/trustedprefixes
License: CC0-1.0
Copyright: 2018 Andrius Štikonas <andrius@stikonas.eu>
Copyright: None

View File

@ -1,35 +1,39 @@
# SPDX-FileCopyrightText: 2008 Volker Lanz <vl@fidra.de>
# SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
# SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2014-2022 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
# SPDX-License-Identifier: GPL-3.0-or-later
project(kpmcore)
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
# KDE Application Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "22")
set (RELEASE_SERVICE_VERSION_MINOR "07")
set (RELEASE_SERVICE_VERSION_MICRO "70")
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(kpmcore VERSION ${RELEASE_SERVICE_VERSION})
set(SOVERSION "12")
add_definitions(-D'VERSION="${RELEASE_SERVICE_VERSION}"') #"
set(CMAKE_USE_RELATIVE_PATHS OFF)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
# Note that KPMcore is restricted to only run binaries installed into trusted prefixes
# See src/util/trustedprefixes
# By default this is set to / and /usr which is good for majority of distros
# Dependencies
set(QT_MIN_VERSION "5.14.0")
set(KF5_MIN_VERSION "5.56")
set(QT_MIN_VERSION "5.15.0")
set(KF5_MIN_VERSION "5.90")
set(BLKID_MIN_VERSION "2.33.2")
# PolkitQt5-1
# Runtime
# smartmontools 7.0
set(VERSION_MAJOR "4")
set(VERSION_MINOR "2")
set(VERSION_RELEASE "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE})
set(SOVERSION "10")
add_definitions(-D'VERSION="${VERSION}"') #"
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(KDE_COMPILERSETTINGS_LEVEL "5.85")
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
@ -42,12 +46,16 @@ include(GenerateExportHeader)
include(ECMSetupVersion)
include(ECMConfiguredInstall)
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
ecm_setup_version(${RELEASE_SERVICE_VERSION} VARIABLE_PREFIX KPMCORE
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KPMcoreConfigVersion.cmake"
SOVERSION ${SOVERSION})
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
if (NOT QT_MAJOR_VERSION)
set(QT_MAJOR_VERSION "5")
endif()
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} COMPONENTS REQUIRED
Core
DBus
Gui
@ -56,26 +64,14 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
# Load the frameworks we need
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED
Auth
CoreAddons
I18n
WidgetsAddons
)
find_package(PolkitQt5-1 REQUIRED)
find_package(PolkitQt${QT_MAJOR_VERSION}-1 REQUIRED)
# use sane compile flags
add_definitions(
-DQT_USE_QSTRINGBUILDER
-DQT_NO_CAST_TO_ASCII
-DQT_NO_CAST_FROM_ASCII
-DQT_STRICT_ITERATORS
-DQT_NO_URL_CAST_FROM_STRING
-DQT_NO_CAST_FROM_BYTEARRAY
-DQT_NO_CAST_TO_BYTEARRAY
-DQT_USE_FAST_OPERATOR_PLUS
-DQT_NO_KEYWORDS
)
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050f00)
kde_enable_exceptions()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
@ -83,18 +79,14 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
pkg_check_modules(BLKID REQUIRED blkid>=${BLKID_MIN_VERSION})
endif()
include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/)
add_subdirectory(src)
# create a Config.cmake and a ConfigVersion.cmake file and install them
set(INCLUDE_INSTALL_DIR "include/kpmcore/")
set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KPMcore")
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KPMcore")
configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KPMcoreConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/KPMcoreConfig.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
PATH_VARS INCLUDE_INSTALL_DIR
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KPMcoreConfig.cmake"
@ -107,10 +99,10 @@ install(EXPORT KPMcoreTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KPMc
ki18n_install(po)
set_target_properties( kpmcore
PROPERTIES VERSION ${VERSION} SOVERSION ${SOVERSION}
PROPERTIES VERSION ${RELEASE_SERVICE_VERSION} SOVERSION ${SOVERSION}
)
message(STATUS "kpmcore ${VERSION} will be built for install into ${CMAKE_INSTALL_PREFIX}")
message(STATUS "kpmcore ${RELEASE_SERVICE_VERSION} will be built for install into ${CMAKE_INSTALL_PREFIX}")
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)

View File

@ -1,9 +1,11 @@
# SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
# SPDX-FileCopyrightText: 2016 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2016-2022 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-License-Identifier: GPL-3.0-or-later
@PACKAGE_INIT@
set_and_check(KPMCORE_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
include(CMakeFindDependencyMacro)
find_dependency(Qt@QT_MAJOR_VERSION@ @QT_MIN_VERSION@ COMPONENTS Core)
include("${CMAKE_CURRENT_LIST_DIR}/KPMcoreTargets.cmake")

View File

@ -1,4 +1,4 @@
<!-- SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
<!-- SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
SPDX-FileCopyrightText: 2017-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-License-Identifier: CC-BY-4.0
-->
@ -35,7 +35,6 @@ looks like this:
```cmake
find_package( KPMcore 3.2 REQUIRED )
include_directories( ${KPMCORE_INCLUDE_DIR} )
target_link_libraries( target kpmcore )
```

17
metainfo.yaml Normal file
View File

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: none
# SPDX-License-Identifier: CC0-1.0
maintainer: stikonas
description: KPMcore, the KDE Partition Manager core, is a library for examining and modifying partitions, disk devices, and filesystems.
platforms:
- name: Linux
release: true
public_lib: true
public_source_dirs:
- src
libraries:
- cmake: kpmcore
cmakename: KPMcore
irc: kde-devel
mailinglist: kde-devel

View File

@ -1,11 +1,16 @@
# SPDX-FileCopyrightText: 2008,2012 Volker Lanz <vl@fidra.de>
# SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
# SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
# SPDX-License-Identifier: GPL-3.0-or-later
add_definitions(-DTRANSLATION_DOMAIN=\"kpmcore\")
include_directories(
${BLKID_INCLUDE_DIRS}
)
include(backend/CMakeLists.txt)
include(core/CMakeLists.txt)
include(util/CMakeLists.txt)
@ -28,24 +33,31 @@ ki18n_wrap_ui(kpmcore_SRCS ${gui_UIFILES})
add_library(kpmcore SHARED ${kpmcore_SRCS})
target_link_libraries( kpmcore PUBLIC
Qt5::Core
Qt::Core
PRIVATE
${BLKID_LIBRARIES}
Qt5::DBus
Qt5::Gui
Qt::DBus
Qt::Gui
KF5::I18n
KF5::CoreAddons
KF5::WidgetsAddons
)
generate_export_header(kpmcore
BASE_NAME LIBKPMCORE
EXPORT_FILE_NAME util/libpartitionmanagerexport.h
)
list(APPEND UTIL_LIB_HDRS ${CMAKE_CURRENT_BINARY_DIR}/util/libpartitionmanagerexport.h)
install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES ${CORE_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/core/ COMPONENT Devel)
install(FILES ${BACKEND_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/backend/ COMPONENT Devel)
install(FILES ${FS_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/fs/ COMPONENT Devel)
install(FILES ${JOBS_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/jobs/ COMPONENT Devel)
install(FILES ${OPS_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/ops/ COMPONENT Devel)
install(FILES ${UTIL_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/util/ COMPONENT Devel)
install(FILES ${GUI_LIB_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/kpmcore/gui/ COMPONENT Devel)
target_include_directories(kpmcore INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}/kpmcore>")
install(TARGETS kpmcore EXPORT KPMcoreTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES ${CORE_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/core/ COMPONENT Devel)
install(FILES ${BACKEND_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/backend/ COMPONENT Devel)
install(FILES ${FS_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/fs/ COMPONENT Devel)
install(FILES ${JOBS_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/jobs/ COMPONENT Devel)
install(FILES ${OPS_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/ops/ COMPONENT Devel)
install(FILES ${UTIL_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/util/ COMPONENT Devel)
install(FILES ${GUI_LIB_HDRS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kpmcore/gui/ COMPONENT Devel)
############################################

View File

@ -4,7 +4,4 @@
# SPDX-License-Identifier: MIT
$EXTRACTRC `find -name \*.rc` >> rc.cpp || exit 11
$EXTRACTRC `find -name \*.ui` >> rc.cpp || exit 12
$XGETTEXT `find -name \*.cc -o -name \*.cpp -o -name \*.h` rc.cpp -o $podir/kpmcore.pot
rm -f rc.cpp
$XGETTEXT $(find -name \*.cc -o -name \*.cpp -o -name \*.h$) -o $podir/kpmcore.pot

26
src/XmlMessages.sh Normal file
View File

@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2020 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-License-Identifier: MIT
function get_files
{
echo util/org.kde.kpmcore.externalcommand.policy
}
function po_for_file
{
case "$1" in
util/org.kde.kpmcore.externalcommand.policy)
echo kpmcore._policy_.po
;;
esac
}
function tags_for_file
{
case "$1" in
util/org.kde.kpmcore.externalcommand.policy)
echo description
echo message
;;
esac
}

View File

@ -14,6 +14,8 @@
#include "util/globallog.h"
#include <QDebug>
#include <QFileInfo>
#include <KLocalizedString>
struct CoreBackendPrivate
{
@ -29,6 +31,20 @@ CoreBackend::~CoreBackend()
{
}
bool CoreBackend::isPolkitInstalledCorrectly() {
// Assume PACKAGE_DATA_DIR is /usr/share, this is defined on polkit on buildtime so this might be wrong.
// This is a warning, not a hard failure, so it does not matter much.
QFileInfo fInfo(QStringLiteral("/usr/share/polkit-1/actions/org.kde.kpmcore.externalcommand.policy"));
// TODO: Port kpm to qCDebug, currently everything is debug.
if (!fInfo.exists()) {
qDebug() << "Installation might be wrong, we can't locate `org.kde.kpmcore.externalcommand.policy` on the polkit actions folder.";
qDebug() << "Please check if your Installation is on a different prefix and copy it to /usr/share/polkit-1/actions";
qDebug() << "That's specified for your distro. Since this is distro specific, you need to look at your distribution documentation.";
}
return fInfo.exists();
}
void CoreBackend::emitProgress(int i)
{
Q_EMIT progress(i);

View File

@ -47,7 +47,7 @@ class LIBKPMCORE_EXPORT CoreBackend : public QObject
protected:
CoreBackend();
virtual ~CoreBackend();
~CoreBackend() override;
Q_SIGNALS:
/**
@ -170,6 +170,8 @@ public:
*/
virtual void emitScanProgress(const QString& deviceNode, int i);
static bool isPolkitInstalledCorrectly();
protected:
static void setPartitionTableForDevice(Device& d, PartitionTable* p);
static void setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_primaries);

View File

@ -1,6 +1,6 @@
/*
SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
SPDX-FileCopyrightText: 2014-2018 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2014-2021 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
@ -17,7 +17,6 @@
#include <KLocalizedString>
#include <KPluginFactory>
#include <KPluginLoader>
#include <KPluginMetaData>
struct CoreBackendManagerPrivate
@ -51,13 +50,7 @@ CoreBackend* CoreBackendManager::backend()
QVector<KPluginMetaData> CoreBackendManager::list() const
{
auto filter = [&](const KPluginMetaData &metaData) {
return metaData.serviceTypes().contains(QStringLiteral("PartitionManager/Plugin")) &&
metaData.category().contains(QStringLiteral("BackendPlugin"));
};
// find backend plugins in standard path (e.g. /usr/lib64/qt5/plugins) using filter from above
return KPluginLoader::findPlugins(QString(), filter);
return KPluginMetaData::findPlugins(QStringLiteral("kpmcore"));
}
bool CoreBackendManager::load(const QString& name)
@ -65,29 +58,25 @@ bool CoreBackendManager::load(const QString& name)
if (backend())
unload();
KPluginLoader loader(name);
QString path = QStringLiteral("kpmcore/") + name;
KPluginFactory* factory = loader.factory();
KPluginMetaData metadata(path);
d->m_Backend = KPluginFactory::instantiatePlugin<CoreBackend>(metadata).plugin;
if (factory != nullptr) {
d->m_Backend = factory->create<CoreBackend>(nullptr);
QString id = loader.metaData().toVariantMap().value(QStringLiteral("MetaData"))
.toMap().value(QStringLiteral("KPlugin")).toMap().value(QStringLiteral("Id")).toString();
QString version = loader.metaData().toVariantMap().value(QStringLiteral("MetaData"))
.toMap().value(QStringLiteral("KPlugin")).toMap().value(QStringLiteral("Version")).toString();
if (id.isEmpty())
return false;
backend()->setId(id);
backend()->setVersion(version);
qDebug() << "Loaded backend plugin: " << backend()->id();
return true;
if (!backend()) {
qWarning() << "Could not create instance of plugin " << name;
return false;
}
qWarning() << "Could not load plugin for core backend " << name << ": " << loader.errorString();
return false;
QString id = metadata.pluginId();
QString version = metadata.version();
if (id.isEmpty())
return false;
backend()->setId(id);
backend()->setVersion(version);
qDebug() << "Loaded backend plugin: " << backend()->id();
return true;
}
void CoreBackendManager::unload()

View File

@ -14,10 +14,10 @@
#include <memory>
#include <QStringList>
#include <QVector>
class QString;
class QStringList;
class KPluginMetaData;
class CoreBackend;
struct CoreBackendManagerPrivate;

View File

@ -56,7 +56,7 @@ public:
public:
explicit Device(const Device& other);
virtual ~Device();
~Device() override;
virtual bool operator==(const Device& other) const;
virtual bool operator!=(const Device& other) const;

View File

@ -82,10 +82,17 @@ FstabEntryList readFstabEntries( const QString& fstabPath )
// (4) dump frequency (optional, defaults to 0), no comment is allowed if omitted,
// (5) pass number (optional, defaults to 0), no comment is allowed if omitted,
// (#) comment (optional).
// Handle deprecated subtypes, e.g. sshfs#example. They are not relevant for partitioning, ignore them.
if (splitLine.size() < 3) {
continue;
}
auto fsSpec = splitLine.at(0);
auto mountPoint = splitLine.at(1);
auto mountPoint = unescapeSpaces(splitLine.at(1));
auto fsType = splitLine.at(2);
auto options = splitLine.at(3);
// Options may be omitted in some rare cases like NixOS generated fstab.
auto options = splitLine.length() >= 4 ? splitLine.at(3) : QStringLiteral("defaults");
switch (splitLine.length()) {
case 4:
@ -110,6 +117,22 @@ FstabEntryList readFstabEntries( const QString& fstabPath )
return fstabEntries;
}
QString escapeSpaces(const QString& mountPoint)
{
QString tmp = mountPoint;
tmp.replace(QStringLiteral(" "), QStringLiteral("\\040"));
tmp.replace(QStringLiteral("\t"), QStringLiteral("\\011"));
return tmp;
}
QString unescapeSpaces(const QString& mountPoint)
{
QString tmp = mountPoint;
tmp.replace(QStringLiteral("\\040"), QStringLiteral(" "));
tmp.replace(QStringLiteral("\\011"), QStringLiteral("\t"));
return tmp;
}
void FstabEntry::setFsSpec(const QString& s)
{
d->m_fsSpec = s;
@ -208,8 +231,8 @@ static QString findBlkIdDevice(const char *token, const QString& value)
free(c);
}
#else
Q_UNUSED(token);
Q_UNUSED(value);
Q_UNUSED(token)
Q_UNUSED(value)
#endif
return rval;
@ -217,7 +240,8 @@ static QString findBlkIdDevice(const char *token, const QString& value)
static void parseFsSpec(const QString& m_fsSpec, FstabEntry::Type& m_entryType, QString& m_deviceNode)
{
m_entryType = FstabEntry::Type::comment;
m_entryType = FstabEntry::Type::other;
m_deviceNode = m_fsSpec;
if (m_fsSpec.startsWith(QStringLiteral("UUID="))) {
m_entryType = FstabEntry::Type::uuid;
m_deviceNode = findBlkIdDevice("UUID", QString(m_fsSpec).remove(QStringLiteral("UUID=")));
@ -232,7 +256,8 @@ static void parseFsSpec(const QString& m_fsSpec, FstabEntry::Type& m_entryType,
m_deviceNode = findBlkIdDevice("PARTLABEL", QString(m_fsSpec).remove(QStringLiteral("PARTLABEL=")));
} else if (m_fsSpec.startsWith(QStringLiteral("/"))) {
m_entryType = FstabEntry::Type::deviceNode;
m_deviceNode = m_fsSpec;
} else if (m_fsSpec.isEmpty()) {
m_entryType = FstabEntry::Type::comment;
}
}
@ -242,7 +267,7 @@ std::array<unsigned int, 4> fstabColumnWidth(const FstabEntryList& fstabEntries)
{
std::array<unsigned int, 4> columnWidth;
#define FIELD_WIDTH(x) 3 + std::max_element(fstabEntries.begin(), fstabEntries.end(), [](const FstabEntry& a, const FstabEntry& b) {return a.x().length() < b.x().length(); })->x().length();
#define FIELD_WIDTH(x) 3 + escapeSpaces(std::max_element(fstabEntries.begin(), fstabEntries.end(), [](const FstabEntry& a, const FstabEntry& b) {return escapeSpaces(a.x()).length() < escapeSpaces(b.x()).length(); })->x()).length();
columnWidth[0] = FIELD_WIDTH(fsSpec);
columnWidth[1] = FIELD_WIDTH(mountPoint);
@ -262,7 +287,7 @@ static void writeEntry(QTextStream& s, const FstabEntry& entry, std::array<unsig
s.setFieldAlignment(QTextStream::AlignLeft);
s.setFieldWidth(columnWidth[0]);
s << entry.fsSpec()
<< qSetFieldWidth(columnWidth[1]) << (entry.mountPoint().isEmpty() ? QStringLiteral("none") : entry.mountPoint())
<< qSetFieldWidth(columnWidth[1]) << (entry.mountPoint().isEmpty() ? QStringLiteral("none") : escapeSpaces(entry.mountPoint()))
<< qSetFieldWidth(columnWidth[2]) << entry.type()
<< qSetFieldWidth(columnWidth[3]) << entry.optionsString() << qSetFieldWidth(0)
<< entry.dumpFreq() << " "
@ -270,7 +295,7 @@ static void writeEntry(QTextStream& s, const FstabEntry& entry, std::array<unsig
<< entry.comment() << "\n";
}
bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename)
bool writeMountpoints(const FstabEntryList& fstabEntries)
{
QString fstabContents;
QTextStream out(&fstabContents);
@ -281,5 +306,5 @@ bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filenam
writeEntry(out, e, columnWidth);
ExternalCommand cmd;
return cmd.createFile(fstabContents.toLocal8Bit(), filename);
return cmd.writeFstab(fstabContents.toLocal8Bit());
}

View File

@ -26,7 +26,7 @@ struct FstabEntryPrivate;
class LIBKPMCORE_EXPORT FstabEntry
{
public:
enum class Type { deviceNode, uuid, label, partlabel, partuuid, comment };
enum class Type { deviceNode, uuid, label, partlabel, partuuid, comment, other };
FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq = 0, int passNumber = 0, const QString& comment = QString());
@ -111,8 +111,11 @@ private:
typedef QList<FstabEntry> FstabEntryList;
QString escapeSpaces(const QString& mountPoint);
QString unescapeSpaces(const QString& mountPoint);
LIBKPMCORE_EXPORT FstabEntryList readFstabEntries(const QString& fstabPath = QStringLiteral("/etc/fstab"));
LIBKPMCORE_EXPORT QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath = QStringLiteral("/etc/fstab"));
LIBKPMCORE_EXPORT bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename = QStringLiteral("/etc/fstab"));
LIBKPMCORE_EXPORT bool writeMountpoints(const FstabEntryList& fstabEntries);
#endif

View File

@ -1,6 +1,6 @@
/*
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2016-2019 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2016-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net>
@ -21,6 +21,8 @@
#include "util/globallog.h"
#include "util/report.h"
#include <utility>
#include <QRegularExpression>
#include <QStorageInfo>
#include <QtMath>
@ -215,7 +217,7 @@ void LvmDevice::scanSystemLVM(QList<Device*>& devices)
// Inform LvmDevice about which physical volumes form that particular LvmDevice
for (const auto &d : lvmList)
for (const auto &p : qAsConst(LVM::pvList::list()))
for (const auto &p : std::as_const(LVM::pvList::list()))
if (p.vgName() == d->name())
d->physicalVolumes().append(p.partition());

View File

@ -24,7 +24,6 @@
class PartitionTable;
class Report;
class Partition;
class SmartStatus;
/** Representation of LVM Volume Group(VG).
@ -40,7 +39,7 @@ class LIBKPMCORE_EXPORT LvmDevice : public VolumeManagerDevice
public:
explicit LvmDevice(const QString& name, const QString& iconName = QString());
~LvmDevice();
~LvmDevice() override;
public:
const QStringList deviceNodes() const override;

View File

@ -45,7 +45,7 @@ public:
public:
explicit OperationStack(QObject* parent = nullptr);
~OperationStack();
~OperationStack() override;
Q_SIGNALS:
void operationsChanged();

View File

@ -264,25 +264,25 @@ private:
m_Number = n;
}
qint32 m_Number;
qint32 m_Number = 0;
Partitions m_Children;
QPointer< PartitionNode > m_Parent;
FileSystem* m_FileSystem;
QPointer< PartitionNode > m_Parent = nullptr;
FileSystem* m_FileSystem = nullptr;
PartitionRole m_Roles;
qint64 m_FirstSector;
qint64 m_LastSector;
qint64 m_FirstSector = 0;
qint64 m_LastSector = 0;
QString m_DevicePath;
QString m_Label;
QString m_Type;
QString m_UUID;
quint64 m_Attributes;
quint64 m_Attributes = 0;
QString m_PartitionPath;
QString m_MountPoint;
PartitionTable::Flags m_AvailableFlags;
PartitionTable::Flags m_ActiveFlags;
bool m_IsMounted;
qint64 m_SectorSize;
State m_State;
bool m_IsMounted = false;
qint64 m_SectorSize = 0;
State m_State = None;
};
QTextStream& operator<<(QTextStream& stream, const Partition& p);

View File

@ -33,7 +33,7 @@ public:
protected:
PartitionNode() {}
virtual ~PartitionNode() {}
~PartitionNode() override {}
public:
virtual bool insert(Partition* partNew);

View File

@ -23,6 +23,8 @@
#include "util/globallog.h"
#include <utility>
#include <KLocalizedString>
#include <QDebug>
@ -592,7 +594,7 @@ QTextStream& operator<<(QTextStream& stream, const PartitionTable& ptable)
std::sort(partitions.begin(), partitions.end(), [](const Partition* p1, const Partition* p2) { return p1->number() < p2->number(); });
for (const auto &p : qAsConst(partitions))
for (const auto &p : std::as_const(partitions))
stream << *p;
return stream;

View File

@ -14,6 +14,8 @@
#include "fs/filesystemfactory.h"
#include "util/externalcommand.h"
#include <utility>
#include <KLocalizedString>
#include <QFile>
#include <QRegularExpression>
@ -221,7 +223,7 @@ void SoftwareRAID::scanSoftwareRAID(QList<Device*>& devices)
}
}
for (const QString& name : qAsConst(availableInConf)) {
for (const QString& name : std::as_const(availableInConf)) {
SoftwareRAID *raidDevice = new SoftwareRAID(name, SoftwareRAID::Status::Inactive);
devices << raidDevice;
}

View File

@ -35,7 +35,7 @@ SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) :
m_Assessment(getAssessment(a)),
m_Value(getPrettyValue(a.prettyValue(), a.prettyUnit()))
{
}
QString SmartAttribute::assessmentToString(Assessment a)
@ -65,7 +65,7 @@ static QString getPrettyValue(quint64 value, SmartAttributeUnit unit)
switch (unit) {
case SmartAttributeUnit::Miliseconds:
rval = KFormat().formatDuration(value);
rval = KFormat().formatSpelloutDuration(value);
break;
case SmartAttributeUnit::Sectors:

View File

@ -1,7 +1,7 @@
/*
SPDX-FileCopyrightText: 2008 Lennart Poettering
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2018-2019 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -9,6 +9,8 @@
#include "smartattributeparseddata.h"
#include "core/smartdiskinformation.h"
#include <utility>
#include <QJsonObject>
#include <QMap>
#include <QRegularExpression>
@ -615,7 +617,7 @@ static SmartQuirk getQuirk(QString model, QString firmware)
QRegularExpression modelRegex;
QRegularExpression firmwareRegex;
for (const SmartAttributeParsedData::SmartQuirkDataBase &item : qAsConst(db)) {
for (const SmartAttributeParsedData::SmartQuirkDataBase &item : std::as_const(db)) {
if (!item.model.isEmpty()) {
modelRegex.setPattern(item.model);
QRegularExpressionMatch match = modelRegex.match(model);

View File

@ -1,6 +1,6 @@
/*
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2018-2019 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -9,6 +9,7 @@
#include "core/smartattributeparseddata.h"
#include <memory>
#include <utility>
static quint64 u64log2(quint64 n);
@ -145,7 +146,7 @@ bool SmartDiskInformation::updatePowerCycle()
/** Validate disk attributes status */
void SmartDiskInformation::validateBadAttributes()
{
for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) {
for (const SmartAttributeParsedData &attribute : std::as_const(m_Attributes)) {
if (attribute.prefailure()) {
if (attribute.goodNowValid() && !attribute.goodNow())
m_BadAttributeNow = true;
@ -161,7 +162,7 @@ void SmartDiskInformation::validateBadAttributes()
SmartAttributeParsedData *SmartDiskInformation::findAttribute(quint32 id)
{
SmartAttributeParsedData *attr = nullptr;
for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) {
for (const SmartAttributeParsedData &attribute : std::as_const(m_Attributes)) {
if (id == attribute.id()) {
attr = new SmartAttributeParsedData(attribute);
break;

View File

@ -1,5 +1,6 @@
/*
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -12,6 +13,7 @@
#include "util/externalcommand.h"
#include <errno.h>
#include <utility>
#include <QDebug>
#include <QJsonArray>
@ -115,7 +117,11 @@ void SmartParser::loadSmartOutput()
if (m_SmartOutput.isEmpty()) {
ExternalCommand smartctl(QStringLiteral("smartctl"), { QStringLiteral("--all"), QStringLiteral("--json"), devicePath() });
if (smartctl.run() && smartctl.exitCode() == 0) {
// Exit status of smartctl is a bitfield, check that bits 0 and 1 are not set:
// - bit 0: command line did not parse;
// - bit 1: device open failed.
// See `man 8 smartctl` for more details.
if (smartctl.run() && (smartctl.exitCode() & 1) == 0 && (smartctl.exitCode() & 2) == 0) {
QByteArray output = smartctl.rawOutput();
m_SmartOutput = QJsonDocument::fromJson(output);
@ -147,7 +153,7 @@ void SmartParser::loadAttributes()
return;
}
for (const QJsonValue &value : qAsConst(attributeArray)) {
for (const QJsonValue &value : std::as_const(attributeArray)) {
SmartAttributeParsedData parsedObject(m_DiskInformation, value.toObject());
m_DiskInformation->addAttribute(parsedObject);
}

View File

@ -1,7 +1,7 @@
/*
SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
SPDX-FileCopyrightText: 2010 Yuri Chornoivan <yurchor@ukr.net>
SPDX-FileCopyrightText: 2014-2019 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
@ -22,6 +22,7 @@
#include <QStringList>
#include <errno.h>
#include <utility>
SmartStatus::SmartStatus(const QString &device_path) :
m_DevicePath(device_path),
@ -144,7 +145,7 @@ void SmartStatus::addAttributes(QList<SmartAttributeParsedData> attr)
{
m_Attributes.clear();
for (const SmartAttributeParsedData &at : qAsConst(attr)) {
for (const SmartAttributeParsedData &at : std::as_const(attr)) {
SmartAttribute sm(at);
m_Attributes.append(sm);
}

View File

@ -42,6 +42,8 @@ public:
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) override;
bool updateUUID(Report& report, const QString& deviceNode) const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -28,6 +28,7 @@ FileSystem::CommandSupportType exfat::m_Backup = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType exfat::m_SetLabel = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType exfat::m_UpdateUUID = FileSystem::cmdSupportNone;
FileSystem::CommandSupportType exfat::m_GetUUID = FileSystem::cmdSupportNone;
bool exfat::exfatUtils = false;
exfat::exfat(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) :
FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Exfat)
@ -36,11 +37,20 @@ exfat::exfat(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QS
void exfat::init()
{
m_Create = findExternal(QStringLiteral("mkfs.exfat")) ? cmdSupportFileSystem : cmdSupportNone;
m_Check = findExternal(QStringLiteral("exfatfsck"), QStringList(), 1) ? cmdSupportFileSystem : cmdSupportNone;
// Check if we are using exfat-utils or exfatprogs
exfatUtils = findExternal(QStringLiteral("mkexfatfs"));
if (exfatUtils) {
m_Create = cmdSupportFileSystem;
m_Check = findExternal(QStringLiteral("fsck.exfat"), {}, 1) ? cmdSupportFileSystem : cmdSupportNone;
m_SetLabel = findExternal(QStringLiteral("exfatlabel")) ? cmdSupportFileSystem : cmdSupportNone;
}
else {
m_Create = findExternal(QStringLiteral("mkfs.exfat"), {}, 1) ? cmdSupportFileSystem : cmdSupportNone;
m_Check = findExternal(QStringLiteral("fsck.exfat"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone;
m_SetLabel = findExternal(QStringLiteral("tune.exfat")) ? cmdSupportFileSystem : cmdSupportNone;
}
m_GetLabel = cmdSupportCore;
m_SetLabel = findExternal(QStringLiteral("exfatlabel")) ? cmdSupportFileSystem : cmdSupportNone;
m_UpdateUUID = cmdSupportNone;
m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone;
@ -70,7 +80,7 @@ bool exfat::supportToolFound() const
FileSystem::SupportTool exfat::supportToolName() const
{
return SupportTool(QStringLiteral("exfat-utils"), QUrl(QStringLiteral("https://github.com/relan/exfat")));
return SupportTool(QStringLiteral("exfatprogs"), QUrl(QStringLiteral("https://github.com/exfatprogs/exfatprogs")));
}
qint64 exfat::maxCapacity() const
@ -85,7 +95,7 @@ int exfat::maxLabelLength() const
bool exfat::check(Report& report, const QString& deviceNode) const
{
ExternalCommand cmd(report, QStringLiteral("exfatfsck"), { deviceNode });
ExternalCommand cmd(report, QStringLiteral("fsck.exfat"), { deviceNode });
return cmd.run(-1) && cmd.exitCode() == 0;
}
@ -97,7 +107,16 @@ bool exfat::create(Report& report, const QString& deviceNode)
bool exfat::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel)
{
ExternalCommand cmd(report, QStringLiteral("exfatlabel"), { deviceNode, newLabel });
ExternalCommand cmd(report);
if (exfatUtils) {
cmd.setCommand(QStringLiteral("exfatlabel"));
cmd.setArgs({ deviceNode, newLabel });
}
else {
cmd.setCommand(QStringLiteral("tune.exfat"));
cmd.setArgs({ deviceNode, QStringLiteral("-L"), newLabel });
}
return cmd.run(-1) && cmd.exitCode() == 0;
}

View File

@ -96,6 +96,9 @@ public:
static CommandSupportType m_SetLabel;
static CommandSupportType m_UpdateUUID;
static CommandSupportType m_GetUUID;
private:
static bool exfatUtils;
};
}

View File

@ -91,6 +91,9 @@ public:
SupportTool supportToolName() const override;
bool supportToolFound() const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
public:
static CommandSupportType m_GetUsed;
static CommandSupportType m_GetLabel;

View File

@ -42,6 +42,9 @@ public:
CommandSupportType supportGrowOnline() const override {
return m_Grow;
}
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
};
}

View File

@ -42,6 +42,9 @@ public:
CommandSupportType supportGrowOnline() const override {
return m_Grow;
}
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
};
}

View File

@ -40,6 +40,8 @@ public:
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
// bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
// bool updateUUID(Report& report, const QString& deviceNode) const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -140,7 +140,8 @@ bool fat12::writeLabel(Report& report, const QString& deviceNode, const QString&
{
report.line() << xi18nc("@info:progress", "Setting label for partition <filename>%1</filename> to %2", deviceNode, newLabel.toUpper());
ExternalCommand cmd(report, QStringLiteral("fatlabel"), { deviceNode, newLabel.toUpper() });
const QString label = newLabel.isEmpty() ? QStringLiteral("-r") : newLabel.toUpper();
ExternalCommand cmd(report, QStringLiteral("fatlabel"), { deviceNode, label });
return cmd.run(-1) && cmd.exitCode() == 0;
}

View File

@ -31,6 +31,7 @@
#include <QFileInfo>
#include <QStandardPaths>
#include <QStorageInfo>
#include <QTemporaryDir>
const std::vector<QColor> FileSystem::defaultColorCode =
{
@ -80,6 +81,7 @@ struct FileSystemPrivate {
qint64 m_SectorsUsed;
QString m_Label;
QString m_UUID;
QString m_posixPermissions;
QStringList m_AvailableFeatures;
QVariantMap m_Features;
};
@ -126,6 +128,67 @@ FileSystem::~FileSystem()
{
}
QString FileSystem::implPosixPermissions() const
{
return d->m_posixPermissions;
}
void FileSystem::implSetPosixPermissions(const QString& permissions)
{
d->m_posixPermissions = permissions;
}
bool FileSystem::execChangePosixPermission(Report& report, const QString& deviceNode)
{
// do nothing if the posix permissions is not used here.
if (d->m_posixPermissions.isEmpty()) {
return true;
}
QTemporaryDir tmpDir;
ExternalCommand mountCmd(report, QStringLiteral("mount"),
{ deviceNode, tmpDir.path() });
bool step = mountCmd.run() && mountCmd.exitCode() == 0;
if (!step) {
return false;
}
ExternalCommand chmodCmd(report, QStringLiteral("chmod"),
// forcing recursive, should be empty but
// programming is weird.
{
d->m_posixPermissions,
tmpDir.path(),
QStringLiteral("--recursive")
});
const bool chmodStep = chmodCmd.run() && chmodCmd.exitCode() == 0;
ExternalCommand umountCmd(report, QStringLiteral("umount"),
// forcing recursive, should be empty but
// programming is weird.
{
deviceNode,
});
const bool umountStep = umountCmd.run() && umountCmd.exitCode() == 0;
// we can't return false if chmodStep fails because we still need to umount
// the drive.
if (!chmodStep) {
return false;
}
if (!umountStep) {
return false;
}
return true;
}
/** Reads the capacity in use on this FileSystem
@param deviceNode the device node for the Partition the FileSystem is on
@return the used capacity in bytes or -1 in case of an error

View File

@ -113,6 +113,9 @@ protected:
FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type);
FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features, FileSystem::Type type);
QString implPosixPermissions() const;
void implSetPosixPermissions(const QString& permissions);
public:
virtual ~FileSystem();
@ -199,6 +202,14 @@ public:
virtual SupportTool supportToolName() const;
virtual bool supportToolFound() const;
virtual QString posixPermissions() const { return QString{}; };
virtual void setPosixPermissions(const QString& permissions) { Q_UNUSED(permissions); };
// Tries to change the posix permission on the filesystem, if the
// filesystem supports it. by supports I mean reimplements `posixPermissions()`
// and setPosixPermissions.
bool execChangePosixPermission(Report& report, const QString& deviceNode);
/**
* Returns the (possibly translated) name of the type of this filesystem.
* @see nameForType()

View File

@ -1,6 +1,6 @@
/*
SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
SPDX-FileCopyrightText: 2012-2019 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2012-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
SPDX-FileCopyrightText: 2017 Pali Rohár <pali.rohar@gmail.com>
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
@ -10,6 +10,8 @@
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <utility>
#include "fs/filesystemfactory.h"
#include "fs/filesystem.h"
@ -92,7 +94,7 @@ void FileSystemFactory::init()
fileSystems.insert(FileSystem::Type::Xfs, new FS::xfs(-1, -1, -1, QString()));
fileSystems.insert(FileSystem::Type::Zfs, new FS::zfs(-1, -1, -1, QString()));
for (const auto &fs : qAsConst(fileSystems))
for (const auto &fs : std::as_const(fileSystems))
fs->init();
qDeleteAll(m_FileSystems);

View File

@ -37,6 +37,8 @@ public:
bool check(Report& report, const QString& deviceNode) const override;
bool create(Report& report, const QString& deviceNode) override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetLabel() const override {
return m_GetLabel;

View File

@ -41,6 +41,8 @@ public:
bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -122,12 +122,6 @@ bool linuxswap::writeLabel(Report& report, const QString& deviceNode, const QStr
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool linuxswap::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel)
{
Q_UNUSED(mountPoint)
return writeLabel(report, deviceNode, newLabel);
}
QString linuxswap::mountTitle() const
{
return xi18nc("@title:menu", "Activate swap");

View File

@ -40,7 +40,6 @@ public:
bool create(Report& report, const QString& deviceNode) override;
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) override;
bool copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const override;
bool updateUUID(Report& report, const QString& deviceNode) const override;
qint64 readUsedCapacity(const QString& deviceNode) const override;
@ -76,9 +75,6 @@ public:
CommandSupportType supportSetLabel() const override {
return m_SetLabel;
}
CommandSupportType supportSetLabelOnline() const override {
return m_SetLabel;
}
CommandSupportType supportUpdateUUID() const override {
return m_UpdateUUID;
}

View File

@ -46,7 +46,7 @@ lvm2_pv::lvm2_pv(qint64 firstsector, qint64 lastsector,
void lvm2_pv::init()
{
CommandSupportType lvmFound = findExternal(QStringLiteral("lvm")) ? cmdSupportFileSystem : cmdSupportNone;
CommandSupportType lvmFound = findExternal(QStringLiteral("lvm"), {}, 3) ? cmdSupportFileSystem : cmdSupportNone;
m_Create = lvmFound;
m_Check = lvmFound;

View File

@ -31,7 +31,10 @@ public:
bool check(Report& report, const QString&deviceNode) const override;
bool create(Report& report, const QString&deviceNode) override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetLabel() const override {
return m_GetLabel;
}

View File

@ -41,6 +41,8 @@ public:
bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool updateUUID(Report& report, const QString& deviceNode) const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -47,7 +47,8 @@ ntfs::ntfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QStr
void ntfs::init()
{
m_Shrink = m_Grow = m_Check = m_GetUsed = findExternal(QStringLiteral("ntfsresize")) ? cmdSupportFileSystem : cmdSupportNone;
m_Shrink = m_Grow = m_Check = findExternal(QStringLiteral("ntfsresize")) ? cmdSupportFileSystem : cmdSupportNone;
m_GetUsed = findExternal(QStringLiteral("ntfsinfo")) ? cmdSupportFileSystem : cmdSupportNone;
m_GetLabel = cmdSupportCore;
m_SetLabel = findExternal(QStringLiteral("ntfslabel")) ? cmdSupportFileSystem : cmdSupportNone;
m_Create = findExternal(QStringLiteral("mkfs.ntfs")) ? cmdSupportFileSystem : cmdSupportNone;
@ -97,18 +98,27 @@ int ntfs::maxLabelLength() const
qint64 ntfs::readUsedCapacity(const QString& deviceNode) const
{
ExternalCommand cmd(QStringLiteral("ntfsresize"), { QStringLiteral("--info"), QStringLiteral("--force"), QStringLiteral("--no-progress-bar"), deviceNode });
ExternalCommand cmd(QStringLiteral("ntfsinfo"), { QStringLiteral("--mft"), QStringLiteral("--force"), deviceNode });
if (cmd.run(-1) && cmd.exitCode() == 0) {
QRegularExpression re(QStringLiteral("Cluster Size: (\\d+)"));
QRegularExpressionMatch reClusterSize = re.match(cmd.output());
qint64 clusterSize = reClusterSize.hasMatch() ? reClusterSize.captured(1).toLongLong() : -1;
QRegularExpression re2(QStringLiteral("Free Clusters: (\\d+)"));
QRegularExpressionMatch reFreeClusters = re2.match(cmd.output());
qint64 freeClusters = reFreeClusters.hasMatch() ? reFreeClusters.captured(1).toLongLong() : -1;
QRegularExpression re3(QStringLiteral("Volume Size in Clusters: (\\d+)"));
QRegularExpressionMatch reVolumeSize = re3.match(cmd.output());
qint64 volumeSize = reVolumeSize.hasMatch() ? reVolumeSize.captured(1).toLongLong() : -1;
qint64 usedBytes = -1;
QRegularExpression re(QStringLiteral("resize at (\\d+) bytes"));
QRegularExpressionMatch reUsedBytes = re.match(cmd.output());
if (reUsedBytes.hasMatch())
usedBytes = reUsedBytes.captured(1).toLongLong();
if (usedBytes > -1)
return usedBytes;
qDebug () << volumeSize << freeClusters << clusterSize;
if (clusterSize > -1 && freeClusters > -1 && volumeSize > -1) {
usedBytes = (volumeSize - freeClusters) * clusterSize;
}
return usedBytes;
}
return -1;

View File

@ -40,6 +40,8 @@ public:
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool updateUUID(Report& report, const QString& deviceNode) const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -38,6 +38,8 @@ public:
qint64 readUsedCapacity(const QString& deviceNode) const override;
bool check(Report& report, const QString& deviceNode) const override;
bool create(Report& report, const QString& deviceNode) override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -44,6 +44,8 @@ public:
bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool updateUUID(Report& report, const QString& deviceNode) const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -38,6 +38,8 @@ public:
bool createWithLabel(Report& report, const QString& deviceNode, const QString& label) override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
bool updateUUID(Report& report, const QString& deviceNode) const override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -13,6 +13,7 @@ namespace FS
{
FileSystem::CommandSupportType unknown::m_Move = FileSystem::cmdSupportCore;
FileSystem::CommandSupportType unknown::m_Copy = FileSystem::cmdSupportCore;
unknown::unknown(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) :
FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Unknown)

View File

@ -37,7 +37,12 @@ public:
return m_Move;
}
CommandSupportType supportCopy() const override {
return m_Copy;
}
static CommandSupportType m_Move;
static CommandSupportType m_Copy;
};
}

View File

@ -41,6 +41,8 @@ public:
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -77,13 +77,6 @@ qint64 zfs::maxCapacity() const
return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
}
bool zfs::remove(Report& report, const QString& deviceNode) const
{
Q_UNUSED(deviceNode)
ExternalCommand cmd(report, QStringLiteral("zpool"), { QStringLiteral("destroy"), QStringLiteral("-f"), label() });
return cmd.run(-1) && cmd.exitCode() == 0;
}
bool zfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel)
{
Q_UNUSED(deviceNode)

View File

@ -35,8 +35,9 @@ public:
public:
void init() override;
bool remove(Report& report, const QString& deviceNode) const override;
bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override;
QString posixPermissions() const override { return implPosixPermissions(); };
void setPosixPermissions(const QString& permissions) override { implSetPosixPermissions(permissions); };
CommandSupportType supportGetUsed() const override {
return m_GetUsed;

View File

@ -33,7 +33,7 @@ class LIBKPMCORE_EXPORT PartWidgetBase : public QWidget
protected:
PartWidgetBase(QWidget* parent) : QWidget(parent) {}
virtual ~PartWidgetBase() {}
~PartWidgetBase() override {}
public:
virtual qint32 borderWidth() const {

View File

@ -31,6 +31,7 @@ set(JOBS_SRC
jobs/setpartflagsjob.cpp
jobs/copyfilesystemjob.cpp
jobs/movefilesystemjob.cpp
jobs/changepermissionsjob.cpp
)
set(JOBS_LIB_HDRS

View File

@ -0,0 +1,44 @@
/*
SPDX-FileCopyrightText: Tomaz Canabrava <tcanabrava@kde.org>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "jobs/changepermissionsjob.h"
#include "core/lvmdevice.h"
#include "core/partition.h"
#include "util/report.h"
#include <KLocalizedString>
/** Creates a new CreateVolumeGroupJob
* @param permission the new permission for the partition, in chmod style.
* @param partition the partition to change the permission.
*/
ChangePermissionJob::ChangePermissionJob(Partition& partition) :
Job(),
m_Partition(partition)
{
}
bool ChangePermissionJob::run(Report& parent)
{
bool rval = false;
auto &fs = m_Partition.fileSystem();
Report* report = jobStarted(parent);
rval = fs.execChangePosixPermission(*report, m_Partition.deviceNode());
jobFinished(*report, rval);
return rval;
}
QString ChangePermissionJob::description() const
{
return xi18nc("@info/plain", "Change the permissions of: <filename>%1</filename> to %2", m_Partition.deviceNode(), m_permissions);
}

View File

@ -0,0 +1,43 @@
/*
SPDX-FileCopyrightText: 2021 Tomaz Canabrava <tcanabrava@kde.org>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef KPMCORE_CHANGEPERMISSIONJOB_H
#define KPMCORE_CHANGEPERMISSIONJOB_H
#include "jobs/job.h"
class Partition;
class Report;
class QString;
/** Check a FileSystem.
@author Volker Lanz <vl@fidra.de>
*/
class ChangePermissionJob : public Job
{
public:
/* Permission should be set in the partition. */
explicit ChangePermissionJob(Partition& p);
public:
bool run(Report& parent) override;
QString description() const override;
protected:
Partition& partition() {
return m_Partition;
}
const Partition& partition() const {
return m_Partition;
}
private:
Partition& m_Partition;
QString m_permissions;
};
#endif

View File

@ -49,7 +49,7 @@ protected:
Job();
public:
virtual ~Job() {}
~Job() override {}
Q_SIGNALS:
void started();

View File

@ -13,6 +13,7 @@
#include "jobs/deletefilesystemjob.h"
#include "jobs/createfilesystemjob.h"
#include "jobs/checkfilesystemjob.h"
#include "jobs/changepermissionsjob.h"
#include "fs/filesystem.h"
#include "fs/filesystemfactory.h"
@ -42,6 +43,10 @@ CreateFileSystemOperation::CreateFileSystemOperation(Device& d, Partition& p, Fi
addJob(deleteJob());
addJob(createJob());
addJob(checkJob());
// if the user never configured a new permission, nothing will run, if he did,
// then we change the permissions on the newly created partition.
addJob(new ChangePermissionJob(p));
}
CreateFileSystemOperation::~CreateFileSystemOperation()

View File

@ -21,6 +21,7 @@
#include "jobs/setfilesystemlabeljob.h"
#include "jobs/setpartflagsjob.h"
#include "jobs/checkfilesystemjob.h"
#include "jobs/changepermissionsjob.h"
#include "fs/filesystem.h"
#include "fs/filesystemfactory.h"
@ -31,37 +32,56 @@
#include <KLocalizedString>
struct NewOperationPrivate
{
NewOperationPrivate(Device& d, Partition* p) :
m_TargetDevice(d),
m_NewPartition(p),
m_CreatePartitionJob(new CreatePartitionJob(d, *p)),
m_SetPartitionLabelJob(nullptr),
m_SetPartitionUUIDJob(nullptr),
m_SetPartitionAttributesJob(nullptr),
m_CreateFileSystemJob(nullptr),
m_SetPartFlagsJob(nullptr),
m_SetFileSystemLabelJob(nullptr),
m_CheckFileSystemJob(nullptr)
{
}
Device& m_TargetDevice;
Partition* m_NewPartition;
CreatePartitionJob* m_CreatePartitionJob;
SetPartitionLabelJob* m_SetPartitionLabelJob;
SetPartitionUUIDJob* m_SetPartitionUUIDJob;
SetPartitionAttributesJob* m_SetPartitionAttributesJob;
CreateFileSystemJob* m_CreateFileSystemJob;
SetPartFlagsJob* m_SetPartFlagsJob;
SetFileSystemLabelJob* m_SetFileSystemLabelJob;
CheckFileSystemJob* m_CheckFileSystemJob;
};
/** Creates a new NewOperation.
@param d the Device to create a new Partition on
@param p pointer to the new Partition to create. May not be nullptr.
*/
NewOperation::NewOperation(Device& d, Partition* p) :
Operation(),
m_TargetDevice(d),
m_NewPartition(p),
m_CreatePartitionJob(new CreatePartitionJob(targetDevice(), newPartition())),
m_SetPartitionLabelJob(nullptr),
m_SetPartitionUUIDJob(nullptr),
m_SetPartitionAttributesJob(nullptr),
m_CreateFileSystemJob(nullptr),
m_SetPartFlagsJob(nullptr),
m_SetFileSystemLabelJob(nullptr),
m_CheckFileSystemJob(nullptr)
d_ptr(std::make_unique<NewOperationPrivate>(d, p))
{
addJob(createPartitionJob());
if (!p->label().isEmpty()) {
m_SetPartitionLabelJob = new SetPartitionLabelJob(targetDevice(), newPartition(), p->label());
d_ptr->m_SetPartitionLabelJob = new SetPartitionLabelJob(targetDevice(), newPartition(), p->label());
addJob(setPartitionLabelJob());
}
if (!p->uuid().isEmpty()) {
m_SetPartitionUUIDJob = new SetPartitionUUIDJob(targetDevice(), newPartition(), p->uuid());
d_ptr->m_SetPartitionUUIDJob = new SetPartitionUUIDJob(targetDevice(), newPartition(), p->uuid());
addJob(setPartitionUUIDJob());
}
if (p->attributes()) {
m_SetPartitionAttributesJob = new SetPartitionAttributesJob(targetDevice(), newPartition(), p->attributes());
d_ptr->m_SetPartitionAttributesJob = new SetPartitionAttributesJob(targetDevice(), newPartition(), p->attributes());
addJob(setPartitionAttributesJob());
}
@ -74,26 +94,90 @@ NewOperation::NewOperation(Device& d, Partition* p) :
// label. The operation stack will merge these operations with this one here
// and if the jobs don't exist things will break.
m_CreateFileSystemJob = new CreateFileSystemJob(targetDevice(), newPartition(), fs.label());
d_ptr->m_CreateFileSystemJob = new CreateFileSystemJob(targetDevice(), newPartition(), fs.label());
addJob(createFileSystemJob());
if (fs.type() == FileSystem::Type::Lvm2_PV) {
m_SetPartFlagsJob = new SetPartFlagsJob(targetDevice(), newPartition(), PartitionTable::Flag::Lvm);
d_ptr->m_SetPartFlagsJob = new SetPartFlagsJob(targetDevice(), newPartition(), PartitionTable::Flag::Lvm);
addJob(setPartFlagsJob());
}
m_SetFileSystemLabelJob = new SetFileSystemLabelJob(newPartition(), fs.label());
d_ptr->m_SetFileSystemLabelJob = new SetFileSystemLabelJob(newPartition(), fs.label());
addJob(setLabelJob());
m_CheckFileSystemJob = new CheckFileSystemJob(newPartition());
d_ptr->m_CheckFileSystemJob = new CheckFileSystemJob(newPartition());
addJob(checkJob());
// if the user never configured a new permission, nothing will run, if he did,
// then we change the permissions on the newly created partition.
addJob(new ChangePermissionJob(newPartition()));
}
}
NewOperation::~NewOperation()
{
if (status() == StatusPending)
delete m_NewPartition;
delete d_ptr->m_NewPartition;
}
Partition& NewOperation::newPartition()
{
return *d_ptr->m_NewPartition;
}
const Partition& NewOperation::newPartition() const
{
return *d_ptr->m_NewPartition;
}
Device& NewOperation::targetDevice()
{
return d_ptr->m_TargetDevice;
}
const Device& NewOperation::targetDevice() const
{
return d_ptr->m_TargetDevice;
}
CreatePartitionJob* NewOperation::createPartitionJob()
{
return d_ptr->m_CreatePartitionJob;
}
SetPartitionLabelJob* NewOperation::setPartitionLabelJob()
{
return d_ptr->m_SetPartitionLabelJob;
}
SetPartitionUUIDJob* NewOperation::setPartitionUUIDJob()
{
return d_ptr->m_SetPartitionUUIDJob;
}
SetPartitionAttributesJob* NewOperation::setPartitionAttributesJob()
{
return d_ptr->m_SetPartitionAttributesJob;
}
CreateFileSystemJob* NewOperation::createFileSystemJob()
{
return d_ptr->m_CreateFileSystemJob;
}
SetPartFlagsJob* NewOperation::setPartFlagsJob()
{
return d_ptr->m_SetPartFlagsJob;
}
SetFileSystemLabelJob* NewOperation::setLabelJob()
{
return d_ptr->m_SetFileSystemLabelJob;
}
CheckFileSystemJob* NewOperation::checkJob()
{
return d_ptr->m_CheckFileSystemJob;
}
bool NewOperation::targets(const Device& d) const
@ -142,6 +226,7 @@ Partition* NewOperation::createNew(const Partition& cloneFrom,
p->sectorSize()));
p->setState(Partition::State::New);
p->setPartitionPath(QString());
p->setAttributes(0);
return p;
}

View File

@ -17,6 +17,7 @@
#include <QString>
struct NewOperationPrivate;
class Device;
class OperationStack;
@ -60,56 +61,23 @@ public:
static Partition* createNew(const Partition& cloneFrom, FileSystem::Type type);
protected:
Partition& newPartition() {
return *m_NewPartition;
}
const Partition& newPartition() const {
return *m_NewPartition;
}
Partition& newPartition();
const Partition& newPartition() const;
Device& targetDevice() {
return m_TargetDevice;
}
const Device& targetDevice() const {
return m_TargetDevice;
}
Device& targetDevice();
const Device& targetDevice() const;
CreatePartitionJob* createPartitionJob() {
return m_CreatePartitionJob;
}
SetPartitionLabelJob* setPartitionLabelJob() {
return m_SetPartitionLabelJob;
}
SetPartitionUUIDJob* setPartitionUUIDJob() {
return m_SetPartitionUUIDJob;
}
SetPartitionAttributesJob* setPartitionAttributesJob() {
return m_SetPartitionAttributesJob;
}
CreateFileSystemJob* createFileSystemJob() {
return m_CreateFileSystemJob;
}
SetPartFlagsJob* setPartFlagsJob() {
return m_SetPartFlagsJob;
}
SetFileSystemLabelJob* setLabelJob() {
return m_SetFileSystemLabelJob;
}
CheckFileSystemJob* checkJob() {
return m_CheckFileSystemJob;
}
CreatePartitionJob* createPartitionJob();
SetPartitionLabelJob* setPartitionLabelJob();
SetPartitionUUIDJob* setPartitionUUIDJob();
SetPartitionAttributesJob* setPartitionAttributesJob();
CreateFileSystemJob* createFileSystemJob();
SetPartFlagsJob* setPartFlagsJob();
SetFileSystemLabelJob* setLabelJob();
CheckFileSystemJob* checkJob();
private:
Device& m_TargetDevice;
Partition* m_NewPartition;
CreatePartitionJob* m_CreatePartitionJob;
SetPartitionLabelJob* m_SetPartitionLabelJob;
SetPartitionUUIDJob* m_SetPartitionUUIDJob;
SetPartitionAttributesJob* m_SetPartitionAttributesJob;
CreateFileSystemJob* m_CreateFileSystemJob;
SetPartFlagsJob* m_SetPartFlagsJob;
SetFileSystemLabelJob* m_SetFileSystemLabelJob;
CheckFileSystemJob* m_CheckFileSystemJob;
std::unique_ptr<NewOperationPrivate> d_ptr;
};
#endif

View File

@ -85,7 +85,7 @@ public:
protected:
Operation();
virtual ~Operation();
~Operation() override;
Q_SIGNALS:
void progress(int);

View File

@ -1,6 +1,6 @@
/*
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2016-2018 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2016-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-License-Identifier: GPL-3.0-or-later
*/
@ -14,6 +14,8 @@
#include "jobs/movephysicalvolumejob.h"
#include "util/helpers.h"
#include <utility>
#include <QString>
#include <KLocalizedString>
@ -55,20 +57,20 @@ ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(LvmDevice& d, const QVect
currentFreePE += lvm2PVFs->freePE();
}
qint64 removedFreePE = 0;
for (const auto &p : qAsConst(toRemoveList)) {
for (const auto &p : std::as_const(toRemoveList)) {
FS::lvm2_pv *lvm2PVFs;
innerFS(p, lvm2PVFs);
removedFreePE += lvm2PVFs->freePE();
}
qint64 freePE = currentFreePE - removedFreePE;
qint64 movePE = 0;
for (const auto &p : qAsConst(toRemoveList)) {
for (const auto &p : std::as_const(toRemoveList)) {
FS::lvm2_pv *lvm2PVFs;
innerFS(p, lvm2PVFs);
movePE += lvm2PVFs->allocatedPE();
}
qint64 growPE = 0;
for (const auto &p : qAsConst(toInsertList)) {
for (const auto &p : std::as_const(toInsertList)) {
growPE += p->capacity() / device().peSize();
}

View File

@ -3,6 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
function(kpmcore_add_plugin name)
kcoreaddons_add_plugin(${name} INSTALL_NAMESPACE "kpmcore")
endfunction()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON)

View File

@ -1,17 +1,15 @@
# SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
# SPDX-FileCopyrightText: 2016-2018 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2016-2021 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-License-Identifier: GPL-3.0-or-later
set (pmdummybackendplugin_SRCS
kpmcore_add_plugin(pmdummybackendplugin)
target_sources(pmdummybackendplugin PRIVATE
dummybackend.cpp
dummydevice.cpp
dummypartitiontable.cpp
${CMAKE_SOURCE_DIR}/src/backend/corebackenddevice.cpp
)
add_library(pmdummybackendplugin SHARED ${pmdummybackendplugin_SRCS})
target_link_libraries(pmdummybackendplugin kpmcore KF5::I18n KF5::CoreAddons)
install(TARGETS pmdummybackendplugin DESTINATION ${KDE_INSTALL_PLUGINDIR})

View File

@ -25,7 +25,7 @@
#include <KLocalizedString>
#include <KPluginFactory>
K_PLUGIN_FACTORY_WITH_JSON(DummyBackendFactory, "pmdummybackendplugin.json", registerPlugin<DummyBackend>();)
K_PLUGIN_CLASS_WITH_JSON(DummyBackend, "pmdummybackendplugin.json")
DummyBackend::DummyBackend(QObject*, const QList<QVariant>&) :
@ -51,7 +51,7 @@ QList<Device*> DummyBackend::scanDevices(const ScanFlags scanFlags)
emitScanProgress(QStringLiteral("/dev/sda"), 100);
return scanDevices(false);
return result;
}
Device* DummyBackend::scanDevice(const QString& deviceNode)

View File

@ -24,11 +24,9 @@ class QString;
*/
class DummyBackend : public CoreBackend
{
friend class KPluginFactory;
Q_DISABLE_COPY(DummyBackend)
private:
public:
DummyBackend(QObject* parent, const QList<QVariant>& args);
public:

View File

@ -18,6 +18,7 @@
"Name[fi]": "Volker Lanz",
"Name[fr]": "Volker Lanz",
"Name[gl]": "Volker Lanz",
"Name[hu]": "Volker Lanz",
"Name[id]": "Volker Lanz",
"Name[it]": "Volker Lanz",
"Name[ko]": "Volker Lanz",
@ -39,7 +40,7 @@
],
"Category": "BackendPlugin",
"Description": "A KDE Partition Manager dummy backend for testing purposes.",
"Description[ca@valencia]": "Un dorsal fals per al gestor de particions del KDE amb la finalitat de fer proves.",
"Description[ca@valencia]": "Un dorsal fals per al gestor de particions de KDE amb la finalitat de fer proves.",
"Description[ca]": "Un dorsal fals per al gestor de particions del KDE amb la finalitat de fer proves.",
"Description[cs]": "Falešná podpůrná vrstva pro správce diskových oddílů KDE pro testovací účely.",
"Description[da]": "En KDE-partitionshåndtering med attrap-backend til testformål.",
@ -52,6 +53,7 @@
"Description[fi]": "KDE:n osionhallinnan valetaustaosa testaustarkoituksiin.",
"Description[fr]": "Un moteur de test pour le gestionnaire de partitions de KDE pour faire des essais.",
"Description[gl]": "Unha infraestrutura de probas para o xestor de particións de KDE.",
"Description[hu]": "KDE partíciókezelő üres modul tesztelési célokra.",
"Description[id]": "Sebuah backend dumi Pengelola Partisi KDE untuk tujuan pengujian.",
"Description[it]": "Un motore fittizio del gestore delle partizioni di KDE per scopi di prova.",
"Description[ko]": "테스트용 KDE 파티션 관리자 더미 백엔드입니다.",
@ -66,15 +68,15 @@
"Description[sv]": "Ett bakgrundsprogram till KDE:s partitionshanterare i testsyfte.",
"Description[uk]": "Тестовий додаток сервера Керування розділами KDE.",
"Description[x-test]": "xxA KDE Partition Manager dummy backend for testing purposes.xx",
"Description[zh_CN]": "测试的 KDE 分区管理器虚拟后端",
"Description[zh_CN]": "用于测试的 KDE 分区管理器虚拟后端程序。",
"Description[zh_TW]": "使用虛設後端的 KDE 磁碟分割區管理員,可用來測試。",
"EnabledByDefault": true,
"Icon": "preferences-plugin",
"Id": "pmdummybackendplugin",
"License": "GPL",
"Name": "KDE Partition Manager Dummy Backend",
"Name[ca@valencia]": "Dorsal fals per al gestor de particions del KDE",
"Name[ca]": "Dorsal fals per al gestor de particions del KDE",
"Name[ca@valencia]": "Dorsal fals del gestor de particions de KDE",
"Name[ca]": "Dorsal fals del gestor de particions del KDE",
"Name[cs]": "Podpůrná vrstva pro správce diskových oddílů pro KDE",
"Name[da]": "KDE-partitionshåndtering med attrap-backend",
"Name[de]": "KDE-Partitionsverwaltung Dummy-Backend",
@ -86,6 +88,7 @@
"Name[fi]": "KDE:n osionhallinnan valetaustaosa",
"Name[fr]": "Moteur de test pour le gestionnaire de partitions de KDE",
"Name[gl]": "Infraestrutura de probas para o xestor de particións de KDE",
"Name[hu]": "KDE partíciókezelő üres modul",
"Name[id]": "Backend Dumi Pengelola Partisi KDE",
"Name[it]": "Motore fittizio del gestore delle partizioni di KDE",
"Name[ko]": "KDE 파티션 관리자 더미 백엔드",
@ -101,11 +104,8 @@
"Name[sv]": "KDE:s partitionshanterare bakgrundsprogram för test",
"Name[uk]": "Тестовий додаток сервера Керування розділами KDE",
"Name[x-test]": "xxKDE Partition Manager Dummy Backendxx",
"Name[zh_CN]": "KDE 分区管理器虚拟后端",
"Name[zh_CN]": "KDE 分区管理器虚拟后端程序",
"Name[zh_TW]": "KDE 磁碟分割區管理員 (虛設後端)",
"ServiceTypes": [
"PartitionManager/Plugin"
],
"Version": "1",
"Website": "http://www.partitionmanager.org"
}

View File

@ -1,9 +1,11 @@
# SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com>
# SPDX-FileCopyrightText: 2018 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2021 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-License-Identifier: GPL-3.0-or-later
set (pmsfdiskbackendplugin_SRCS
kpmcore_add_plugin(pmsfdiskbackendplugin)
target_sources(pmsfdiskbackendplugin PRIVATE
sfdiskbackend.cpp
sfdiskdevice.cpp
sfdiskgptattributes.cpp
@ -14,8 +16,4 @@ set (pmsfdiskbackendplugin_SRCS
${CMAKE_SOURCE_DIR}/src/core/copytargetbytearray.cpp
)
add_library(pmsfdiskbackendplugin SHARED ${pmsfdiskbackendplugin_SRCS})
target_link_libraries(pmsfdiskbackendplugin kpmcore KF5::I18n KF5::CoreAddons)
install(TARGETS pmsfdiskbackendplugin DESTINATION ${KDE_INSTALL_PLUGINDIR})

View File

@ -18,6 +18,7 @@
"Name[fi]": "Andrius Štikonas",
"Name[fr]": "Andrius Štikonas",
"Name[gl]": "Andrius Štikonas",
"Name[hu]": "Andrius Štikonas",
"Name[id]": "Andrius Štikonas",
"Name[it]": "Andrius Štikonas",
"Name[ko]": "Andrius Štikonas",
@ -39,7 +40,7 @@
],
"Category": "BackendPlugin",
"Description": "A KDE Partition Manager sfdisk backend.",
"Description[ca@valencia]": "Un dorsal «sfdisk» del gestor de particions del KDE.",
"Description[ca@valencia]": "Un dorsal «sfdisk» del gestor de particions de KDE.",
"Description[ca]": "Un dorsal «sfdisk» del gestor de particions del KDE.",
"Description[cs]": "Podpůrná vrstva sfdisk pro správce diskových oddílů pro KDE.",
"Description[da]": "En KDE-partitionshåndtering med sfdisk-backend.",
@ -52,6 +53,7 @@
"Description[fi]": "KDE:n osionhallinnan sfdisk-taustaosa",
"Description[fr]": "Moteur sfdisk pour le gestionnaire de partitions de KDE.",
"Description[gl]": "Unha infraestrutura de sfdisk para o xestor de particións de KDE.",
"Description[hu]": "KDE partíciókezelő sfdisk modul.",
"Description[id]": "Sebuah backend sfdisk Pengelola Partisi KDE",
"Description[it]": "Un motore sfdisk del gestore delle partizioni di KDE.",
"Description[ko]": "KDE 파티션 관리자 sfdisk 백엔드입니다.",
@ -66,13 +68,14 @@
"Description[sv]": "Ett sfdisk bakgrundsprogram till KDE:s partitionshanterare",
"Description[uk]": "Додаток sfdisk сервера Керування розділами KDE.",
"Description[x-test]": "xxA KDE Partition Manager sfdisk backend.xx",
"Description[zh_CN]": "KDE 分区管理器 sfdisk 后端程序。",
"Description[zh_TW]": "使用 sfdisk 作為後端的 KDE 磁碟分割區管理員。",
"EnabledByDefault": true,
"Icon": "preferences-plugin",
"Id": "pmsfdiskbackendplugin",
"License": "GPL",
"Name": "KDE Partition Manager sfdisk Backend",
"Name[ca@valencia]": "Dorsal «sfdisk» del gestor de particions del KDE",
"Name[ca@valencia]": "Dorsal «sfdisk» del gestor de particions de KDE",
"Name[ca]": "Dorsal «sfdisk» del gestor de particions del KDE",
"Name[cs]": "Podpůrná vrstva sfdisk pro správce diskových oddílů pro KDE",
"Name[da]": "KDE-partitionshåndtering med sfdisk-backend",
@ -85,6 +88,7 @@
"Name[fi]": "KDE:n osionhallinnan sfdisk-taustaosa",
"Name[fr]": "Moteur sfdisk pour le gestionnaire de partitions de KDE",
"Name[gl]": "Infraestrutura de sfdisk para o xestor de particións de KDE",
"Name[hu]": "KDE partíciókezelő sfdisk modul",
"Name[id]": "Backend sfdisk Pengelola Partisi KDE",
"Name[it]": "Motore sfdisk del gestore delle partizioni di KDE",
"Name[ko]": "KDE 파티션 관리자 sfdisk 백엔드",
@ -99,10 +103,8 @@
"Name[sv]": "KDE:s partitionshanterare sfdisk bakgrundsprogram",
"Name[uk]": "Додаток sfdisk сервера Керування розділами KDE",
"Name[x-test]": "xxKDE Partition Manager sfdisk Backendxx",
"Name[zh_CN]": "KDE 分区管理器 sfdisk 后端程序",
"Name[zh_TW]": "KDE 磁碟分割區管理員 (sfdisk 後端)",
"ServiceTypes": [
"PartitionManager/Plugin"
],
"Version": "1",
"Website": "http://www.partitionmanager.org"
}

View File

@ -31,6 +31,8 @@
#include "util/externalcommand.h"
#include "util/helpers.h"
#include <utility>
#include <QDataStream>
#include <QDebug>
#include <QFile>
@ -45,7 +47,7 @@
#include <KLocalizedString>
#include <KPluginFactory>
K_PLUGIN_FACTORY_WITH_JSON(SfdiskBackendFactory, "pmsfdiskbackendplugin.json", registerPlugin<SfdiskBackend>();)
K_PLUGIN_CLASS_WITH_JSON(SfdiskBackend, "pmsfdiskbackendplugin.json")
SfdiskBackend::SfdiskBackend(QObject*, const QList<QVariant>&) :
CoreBackend()
@ -278,7 +280,7 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode)
{
QList<Device *> availableDevices = scanDevices();
for (Device *device : qAsConst(availableDevices))
for (Device *device : std::as_const(availableDevices))
if (device->deviceNode() == deviceNode)
return device;
}
@ -340,7 +342,7 @@ void SfdiskBackend::scanDevicePartitions(Device& d, const QJsonArray& jsonPartit
if (d.partitionTable()->isSectorBased(d))
d.partitionTable()->setType(d, PartitionTable::msdos_sectorbased);
for (const Partition *part : qAsConst(partitions))
for (const Partition *part : std::as_const(partitions))
PartitionAlignment::isAligned(d, *part);
}
@ -449,11 +451,12 @@ bool SfdiskBackend::updateDevicePartitionTable(Device &d, const QJsonObject &jso
// Read the maximum number of GPT partitions
qint32 maxEntries;
QByteArray gptHeader;
CopySourceDevice source(d, 512, 1023);
CopyTargetByteArray target(gptHeader);
qint64 sectorSize = d.logicalSize();
CopySourceDevice source(d, sectorSize, sectorSize * 2 - 1);
ExternalCommand copyCmd;
if (copyCmd.copyBlocks(source, target)) {
ExternalCommand readCmd;
gptHeader = readCmd.readData(source);
if (gptHeader != QByteArray()) {
QByteArray gptMaxEntries = gptHeader.mid(80, 4);
QDataStream stream(&gptMaxEntries, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);

View File

@ -27,11 +27,9 @@ class QString;
*/
class SfdiskBackend : public CoreBackend
{
friend class KPluginFactory;
Q_DISABLE_COPY(SfdiskBackend)
private:
public:
SfdiskBackend(QObject* parent, const QList<QVariant>& args);
public:

View File

@ -60,7 +60,7 @@ bool SfdiskDevice::createPartitionTable(Report& report, const PartitionTable& pt
else
tableType = ptable.typeName().toLocal8Bit();
ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { m_device->deviceNode() } );
ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--wipe=always"), m_device->deviceNode() } );
if ( createCommand.write(QByteArrayLiteral("label: ") + tableType +
QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) ) {
return createCommand.output().contains(QStringLiteral("Script header accepted."));

View File

@ -20,7 +20,7 @@ class CoreBackendPartitionTable;
class SfdiskDevice : public CoreBackendDevice
{
Q_DISABLE_COPY(SfdiskDevice);
Q_DISABLE_COPY(SfdiskDevice)
public:
explicit SfdiskDevice(const Device& d);

View File

@ -8,6 +8,7 @@
#include <QString>
#include <QStringList>
#include <QStringView>
const static QString requiredPartition = QStringLiteral("RequiredPartition");
const static QString noBlockIoProtocol = QStringLiteral("NoBlockIOProtocol");
@ -25,7 +26,7 @@ quint64 SfdiskGptAttributes::toULongLong(const QStringList& attrs)
else if (attr.compare(legacyBiosBootable) == 0)
attributes |= 0x4ULL;
else if (attr.startsWith(guid))
attributes |= 1ULL << QStringRef(&attr, guid.length(), attr.length() - guid.length()).toULongLong();
attributes |= 1ULL << QStringView{ attr }.mid(guid.length(), attr.length() - guid.length()).toULongLong();
return attributes;
}

View File

@ -8,8 +8,7 @@
#define SFDISKGPTATTRIBUTES__H
#include <QtGlobal>
class QStringList;
#include <QStringList>
/** Sfdisk GPT Attributes helpers.
@author Gaël PORTAY <gael.portay@collabora.com>

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2008,2012 Volker Lanz <vl@fidra.de>
# SPDX-FileCopyrightText: 2015 Chris Campbell <c.j.campbell@ed.ac.uk>
# SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
# SPDX-FileCopyrightText: 2015 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2015-2020 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
# SPDX-FileCopyrightText: 2019 Albert Astals Cid <aacid@kde.org>
# SPDX-FileCopyrightText: 2019 Antonio Rojas <arojas@archlinux.org>
@ -11,19 +11,29 @@
set(helper_interface_xml org.kde.kpmcore.helperinterface.xml)
qt5_generate_dbus_interface(
file(READ "util/trustedprefixes" TRUSTED_PREFIXES)
string(REGEX REPLACE ";" "\\\\;" TRUSTED_PREFIXES "${TRUSTED_PREFIXES}")
string(REGEX REPLACE "\n" ";" TRUSTED_PREFIXES "${TRUSTED_PREFIXES}")
foreach(TRUSTED_PREFIX ${TRUSTED_PREFIXES})
list(APPEND TRUSTED_PREFIXES_LIST " QStringLiteral(\"${TRUSTED_PREFIX}\")")
endforeach()
string(REPLACE "; QStringLiteral(" ",\n QStringLiteral(" TRUSTED_PREFIXES_LIST "${TRUSTED_PREFIXES_LIST}")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS util/trustedprefixes)
configure_file(util/externalcommand_trustedprefixes.h.in util/externalcommand_trustedprefixes.h)
qt_generate_dbus_interface(
util/externalcommand.h
${application_interface_xml}
OPTIONS -a
)
qt5_generate_dbus_interface(
qt_generate_dbus_interface(
util/externalcommandhelper.h
${helper_interface_xml}
OPTIONS -a
)
qt5_add_dbus_interface(HelperInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${helper_interface_xml} externalcommandhelper_interface)
qt_add_dbus_interface(HelperInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${helper_interface_xml} externalcommandhelper_interface)
set(UTIL_SRC
${HelperInterface_SRCS}
@ -36,7 +46,6 @@ set(UTIL_SRC
)
set(UTIL_LIB_HDRS
util/libpartitionmanagerexport.h
util/capacity.h
util/externalcommand.h
util/globallog.h
@ -50,16 +59,16 @@ add_executable(kpmcore_externalcommand
)
target_link_libraries(kpmcore_externalcommand
Qt5::Core
Qt5::DBus
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::DBus
KF5::I18n
PolkitQt5-1::Core
PolkitQt${QT_MAJOR_VERSION}-1::Core
)
install(TARGETS kpmcore_externalcommand DESTINATION ${KDE_INSTALL_LIBEXECDIR})
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
install( FILES util/org.kde.kpmcore.externalcommand.policy DESTINATION ${POLKITQT-1_POLICY_FILES_INSTALL_DIR})
ecm_install_configured_files(
INPUT util/org.kde.kpmcore.helperinterface.service.in
DESTINATION ${KDE_INSTALL_DBUSDIR}/system-services

View File

@ -160,7 +160,7 @@ bool ExternalCommand::copyBlocks(const CopySource& source, CopyTarget& target)
connect(interface, &OrgKdeKpmcoreExternalcommandInterface::progress, this, &ExternalCommand::progress);
connect(interface, &OrgKdeKpmcoreExternalcommandInterface::report, this, &ExternalCommand::reportSignal);
QDBusPendingCall pcall = interface->CopyBlocks(source.path(), source.firstByte(), source.length(),
QDBusPendingCall pcall = interface->CopyFileData(source.path(), source.firstByte(), source.length(),
target.path(), target.firstByte(), blockSize);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
@ -187,6 +187,38 @@ bool ExternalCommand::copyBlocks(const CopySource& source, CopyTarget& target)
return rval;
}
QByteArray ExternalCommand::readData(const CopySourceDevice& source)
{
auto interface = helperInterface();
if (!interface)
return {};
// Helper is restricted not to resolve symlinks
QFileInfo sourceInfo(source.path());
QDBusPendingCall pcall = interface->ReadData(sourceInfo.canonicalFilePath(), source.firstByte(), source.length());
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
QEventLoop loop;
QByteArray target;
auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) {
loop.exit();
if (watcher->isError())
qWarning() << watcher->error();
else {
QDBusPendingReply<QByteArray> reply = *watcher;
target = reply.value();
}
};
connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop);
loop.exec();
return target;
}
bool ExternalCommand::writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte)
{
d->m_Report = commandReport.newChild();
@ -201,13 +233,13 @@ bool ExternalCommand::writeData(Report& commandReport, const QByteArray& buffer,
return waitForDbusReply(pcall);
}
bool ExternalCommand::createFile(const QByteArray& fileContents, const QString& filePath)
bool ExternalCommand::writeFstab(const QByteArray& fileContents)
{
auto interface = helperInterface();
if (!interface)
return false;
QDBusPendingCall pcall = interface->CreateFile(filePath, fileContents);
QDBusPendingCall pcall = interface->WriteFstab(fileContents);
return waitForDbusReply(pcall);
}

View File

@ -27,6 +27,7 @@
class KJob;
class Report;
class CopySource;
class CopySourceDevice;
class CopyTarget;
class QDBusInterface;
class QDBusPendingCall;
@ -50,12 +51,13 @@ public:
explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels);
explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels);
~ExternalCommand();
~ExternalCommand() override;
public:
bool copyBlocks(const CopySource& source, CopyTarget& target);
QByteArray readData(const CopySourceDevice& source);
bool writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte); // same as copyBlocks but from QByteArray
bool createFile(const QByteArray& filePath, const QString& fileContents); // similar to writeData but creates a new file
bool writeFstab(const QByteArray& fileContents);
/**< @param cmd the command to run */
void setCommand(const QString& cmd);
@ -72,7 +74,6 @@ public:
bool write(const QByteArray& input); /**< @param input the input for the program */
bool startCopyBlocks();
bool start(int timeout = 30000);
bool run(int timeout = 30000);

View File

@ -0,0 +1,8 @@
/*
SPDX-FileCopyrightText: 2022 Andrius Štikonas <andrius@stikonas.eu>
SPDX-License-Identifier: GPL-3.0-or-later
*/
const std::unordered_set<QString> trustedPrefixes {
@TRUSTED_PREFIXES_LIST@
};

View File

@ -8,7 +8,10 @@
#ifndef KPMCORE_EXTERNALCOMMAND_WHITELIST_H
#define KPMCORE_EXTERNALCOMMAND_WHITELIST_H
QString allowedCommands[] = {
#include <unordered_set>
#include "util/externalcommand_trustedprefixes.h"
const std::unordered_set<QString> allowedCommands {
// TODO no root needed
QStringLiteral("lsblk"),
QStringLiteral("udevadm"),
@ -16,6 +19,7 @@ QStringLiteral("udevadm"),
//Core programs
QStringLiteral("blockdev"),
QStringLiteral("blkid"),
QStringLiteral("chmod"),
QStringLiteral("partx"),
QStringLiteral("sfdisk"),
QStringLiteral("wipefs"),
@ -29,9 +33,11 @@ QStringLiteral("smartctl"),
QStringLiteral("btrfs"),
QStringLiteral("mkfs.btrfs"),
QStringLiteral("btrfstune"),
QStringLiteral("exfatfsck"),
QStringLiteral("fsck.exfat"),
QStringLiteral("mkexfatfs"),
QStringLiteral("mkfs.exfat"),
QStringLiteral("exfatlabel"),
QStringLiteral("tune.exfat"),
QStringLiteral("dumpe2fs"),
QStringLiteral("e2fsck"),
QStringLiteral("mkfs.ext2"),
@ -70,6 +76,7 @@ QStringLiteral("nilfs-resize"),
QStringLiteral("ntfsresize"),
QStringLiteral("mkfs.ntfs"),
QStringLiteral("ntfsclone"),
QStringLiteral("ntfsinfo"),
QStringLiteral("ntfslabel"),
QStringLiteral("fsck.ocfs2"),
QStringLiteral("mkfs.ocfs2"),

View File

@ -1,5 +1,5 @@
/*
SPDX-FileCopyrightText: 2017-2020 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2017-2022 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2018-2019 Harald Sitter <sitter@kde.org>
@ -13,12 +13,16 @@
#include "externalcommandhelper.h"
#include "externalcommand_whitelist.h"
#include <filesystem>
#include <QtDBus>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QElapsedTimer>
#include <QFile>
#include <QFileInfo>
#include <QString>
#include <QVariant>
@ -42,11 +46,11 @@
ExternalCommandHelper::ExternalCommandHelper()
{
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
::exit(-1);
exit(-1);
}
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
::exit(-1);
exit(-1);
}
// we know this service must be registered already as DBus policy blocks calls from anyone else
@ -69,83 +73,85 @@ ExternalCommandHelper::ExternalCommandHelper()
@param size the number of bytes to read
@return true on success
*/
bool ExternalCommandHelper::readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size)
bool ExternalCommandHelper::readData(QFile& device, QByteArray& buffer, const qint64 offset, const qint64 size)
{
QFile device(sourceDevice);
if (!device.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
qCritical() << xi18n("Could not open device <filename>%1</filename> for reading.", sourceDevice);
return false;
if (!device.isOpen()) {
if (!device.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
qCritical() << xi18n("Could not open device <filename>%1</filename> for reading.", device.fileName());
return false;
}
}
if (!device.seek(offset)) {
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, sourceDevice);
// Sequential devices such as /dev/zero or /dev/urandom return false on seek().
if (!device.isSequential() && !device.seek(offset)) {
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, device.fileName());
return false;
}
buffer = device.read(size);
if (size != buffer.size()) {
qCritical() << xi18n("Could not read from device <filename>%1</filename>.", sourceDevice);
return false;
qCritical() << xi18n("Could not read from device <filename>%1</filename>.", device.fileName());
return false;
}
return true;
}
/** Writes the data from buffer to a given device.
@param targetDevice device or file to write to
@param device device or file to write to
@param buffer the data that we write
@param offset offset where to begin writing
@return true on success
*/
bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteArray& buffer, const qint64 offset)
bool ExternalCommandHelper::writeData(QFile& device, const QByteArray& buffer, const qint64 offset)
{
QFile device(targetDevice);
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered | QIODevice::Append;
if (!device.open(flags)) {
qCritical() << xi18n("Could not open device <filename>%1</filename> for writing.", targetDevice);
return false;
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
if (!device.isOpen()) {
if (!device.open(flags)) {
qCritical() << xi18n("Could not open device <filename>%1</filename> for writing.", device.fileName());
return false;
}
}
if (!device.seek(offset)) {
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, targetDevice);
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, device.fileName());
return false;
}
if (device.write(buffer) != buffer.size()) {
qCritical() << xi18n("Could not write to device <filename>%1</filename>.", targetDevice);
qCritical() << xi18n("Could not write to device <filename>%1</filename>.", device.fileName());
return false;
}
return true;
}
/** Creates a new file with given contents.
@param filePath file to write to
@param fileContents the data that we write
/** Creates a new fstab file with given contents.
@param Contents the data that we write
@return true on success
*/
bool ExternalCommandHelper::CreateFile(const QString &filePath, const QByteArray& fileContents)
bool ExternalCommandHelper::WriteFstab(const QByteArray& fstabContents)
{
if (!isCallerAuthorized()) {
return false;
}
// Do not allow using this helper for writing to arbitrary location
if ( !filePath.contains(QStringLiteral("/etc/fstab")) )
if (fstabContents.size() > MiB) {
qCritical() << QStringLiteral("/etc/fstab size limit exceeded.");
return false;
}
QString fstabPath = QStringLiteral("/etc/fstab");
QFile fstabFile(fstabPath);
QFile device(filePath);
// WriteOnly implies O_TRUNC
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
if (!device.open(flags)) {
qCritical() << xi18n("Could not open file <filename>%1</filename> for writing.", filePath);
if (!fstabFile.open(flags)) {
qCritical() << xi18n("Could not open file <filename>%1</filename> for writing.", fstabPath);
return false;
}
if (device.write(fileContents) != fileContents.size()) {
qCritical() << xi18n("Could not write to file <filename>%1</filename>.", filePath);
if (fstabFile.write(fstabContents) != fstabContents.size()) {
qCritical() << xi18n("Could not write to file <filename>%1</filename>.", fstabPath);
return false;
}
@ -153,29 +159,72 @@ bool ExternalCommandHelper::CreateFile(const QString &filePath, const QByteArray
}
// If targetDevice is empty then return QByteArray with data that was read from disk.
QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
QVariantMap ExternalCommandHelper::CopyFileData(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength, const QString& targetDevice, const qint64 targetOffset, const qint64 chunkSize)
{
if (!isCallerAuthorized()) {
return QVariantMap();
return {};
}
// Avoid division by zero further down
if (!chunkSize) {
return {};
}
// Prevent some out of memory situations
if (chunkSize > 100 * MiB) {
return {};
}
// Check for relative paths
std::filesystem::path sourcePath(sourceDevice.toStdU16String());
std::filesystem::path targetPath(targetDevice.toStdU16String());
if(sourcePath.is_relative() || targetPath.is_relative()) {
return {};
}
// Only allow writing to existing files.
if(!std::filesystem::exists(targetPath)) {
return {};
}
QVariantMap reply;
reply[QStringLiteral("success")] = true;
const qint64 blocksToCopy = sourceLength / blockSize;
qint64 readOffset = sourceFirstByte;
qint64 writeOffset = targetFirstByte;
qint32 copyDirection = 1;
// This enum specified whether individual data chunks are moved left or right
// When source and target devices are the same we have to be careful not to overwrite
// source data with newly written data. We don't have to do this if sourceDevice is not
// targetDevice but there are no disadvantages in applying the same scheme.
// When partition is moved to the left, we start with the leftmost chunk,
// and move it further left, then second leftmost chunk and so on.
// But when we move partition to the right, we start with rightmost chunk.
// To account for this difference, we introduce CopyDirection variable which takes
// care of some of the differences in offset calculation between these two cases.
enum CopyDirection : qint8 {
Left = 1,
Right = -1,
};
qint8 copyDirection = targetOffset > sourceOffset ? CopyDirection::Right : CopyDirection::Left;
if (targetFirstByte > sourceFirstByte) {
readOffset = sourceFirstByte + sourceLength - blockSize;
writeOffset = targetFirstByte + sourceLength - blockSize;
copyDirection = -1;
// Let readOffset (r) and writeOffset (w) be the offsets of the first chunk that we move.
// When we move data to the left:
// ______target______ ______source______
// r <- w=================
qint64 readOffset = sourceOffset;
qint64 writeOffset = targetOffset;
// When we move data to the right, we start moving data from the last chunk
// ______source______ ______target______
// =================r -> w
if (copyDirection == CopyDirection::Right) {
readOffset = sourceOffset + sourceLength - chunkSize;
writeOffset = targetOffset + sourceLength - chunkSize;
}
const qint64 lastBlock = sourceLength % blockSize;
const qint64 chunksToCopy = sourceLength / chunkSize;
const qint64 lastBlock = sourceLength % chunkSize;
qint64 bytesWritten = 0;
qint64 blocksCopied = 0;
qint64 chunksCopied = 0;
QByteArray buffer;
int percent = 0;
@ -183,27 +232,29 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
timer.start();
QString reportText = xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy,
sourceLength, readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left")
QString reportText = xi18nc("@info:progress", "Copying %1 chunks (%2 bytes) from %3 to %4, direction: %5.", chunksToCopy,
sourceLength, readOffset, writeOffset, copyDirection == CopyDirection::Left ? i18nc("direction: left", "left")
: i18nc("direction: right", "right"));
Q_EMIT report(reportText);
bool rval = true;
while (blocksCopied < blocksToCopy && !targetDevice.isEmpty()) {
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
QFile target(targetDevice);
QFile source(sourceDevice);
while (chunksCopied < chunksToCopy) {
if (!(rval = readData(source, buffer, readOffset + chunkSize * chunksCopied * copyDirection, chunkSize)))
break;
if (!(rval = writeData(targetDevice, buffer, writeOffset + blockSize * blocksCopied * copyDirection)))
if (!(rval = writeData(target, buffer, writeOffset + chunkSize * chunksCopied * copyDirection)))
break;
bytesWritten += buffer.size();
if (++blocksCopied * 100 / blocksToCopy != percent) {
percent = blocksCopied * 100 / blocksToCopy;
if (++chunksCopied * 100 / chunksToCopy != percent) {
percent = chunksCopied * 100 / chunksToCopy;
if (percent % 5 == 0 && timer.elapsed() > 1000) {
const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (timer.elapsed() / 1000);
const qint64 mibsPerSec = (chunksCopied * chunkSize / 1024 / 1024) / (timer.elapsed() / 1000);
const qint64 estSecsLeft = (100 - percent) * timer.elapsed() / percent / 1000;
reportText = xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString());
Q_EMIT report(reportText);
@ -214,19 +265,16 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
// copy the remainder
if (rval && lastBlock > 0) {
Q_ASSERT(lastBlock < blockSize);
Q_ASSERT(lastBlock < chunkSize);
const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : sourceFirstByte;
const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte;
reportText = xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
const qint64 lastBlockReadOffset = copyDirection == CopyDirection::Left ? readOffset + chunkSize * chunksCopied : sourceOffset;
const qint64 lastBlockWriteOffset = copyDirection == CopyDirection::Left ? writeOffset + chunkSize * chunksCopied : targetOffset;
reportText = xi18nc("@info:progress", "Copying remainder of chunk size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
Q_EMIT report(reportText);
rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock);
rval = readData(source, buffer, lastBlockReadOffset, lastBlock);
if (rval) {
if (targetDevice.isEmpty())
reply[QStringLiteral("targetByteArray")] = buffer;
else
rval = writeData(targetDevice, buffer, lastBlockWriteOffset);
rval = writeData(target, buffer, lastBlockWriteOffset);
}
if (rval) {
@ -235,14 +283,48 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
}
}
reportText = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", bytesWritten));
reportText = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 chunk (%2) finished.", "Copying %1 chunks (%2) finished.", chunksCopied, i18np("1 byte", "%1 bytes", bytesWritten));
Q_EMIT report(reportText);
reply[QStringLiteral("success")] = rval;
return reply;
}
bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte)
QByteArray ExternalCommandHelper::ReadData(const QString& device, const qint64 offset, const qint64 length)
{
if (!isCallerAuthorized()) {
return {};
}
if (length > MiB) {
return {};
}
if (!std::filesystem::is_block_file(device.toStdU16String())) {
qWarning() << "Not a block device";
return {};
}
// Do not follow symlinks
QFileInfo info(device);
if (info.isSymbolicLink()) {
qWarning() << "ReadData: device should not be symbolic link";
return {};
}
if (device.left(5) != QStringLiteral("/dev/") || device.left(9) != QStringLiteral("/dev/shm/")) {
qWarning() << "Error: trying to read data from device not in /dev";
return {};
}
QByteArray buffer;
QFile sourceDevice(device);
bool rval = readData(sourceDevice, buffer, offset, length);
if (rval) {
return buffer;
}
return QByteArray();
}
bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetOffset)
{
if (!isCallerAuthorized()) {
return false;
@ -251,44 +333,74 @@ bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& t
if ( targetDevice.left(5) != QStringLiteral("/dev/") )
return false;
return writeData(targetDevice, buffer, targetFirstByte);
auto targetPath = std::filesystem::path(targetDevice.toStdU16String());
if (!std::filesystem::is_block_file(targetDevice.toStdU16String())) {
qWarning() << "Not a block device";
return {};
}
auto canonicalTargetPath = std::filesystem::canonical(targetPath);
// TODO: Qt6 supports std::filesystem::path
QFile device(QLatin1String(canonicalTargetPath.c_str()));
return writeData(device, buffer, targetOffset);
}
QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
{
if (!isCallerAuthorized()) {
return QVariantMap();
return {};
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
#endif
QVariantMap reply;
reply[QStringLiteral("success")] = true;
reply[QStringLiteral("success")] = false;
if (command.isEmpty()) {
reply[QStringLiteral("success")] = false;
return reply;
}
// Compare with command whitelist
QString basename = command.mid(command.lastIndexOf(QLatin1Char('/')) + 1);
if (std::find(std::begin(allowedCommands), std::end(allowedCommands), basename) == std::end(allowedCommands)) {
qInfo() << command <<" command is not one of the whitelisted command";
qApp->quit();
QFileInfo fileInfo(command);
QString basename = fileInfo.fileName();
if (allowedCommands.find(basename) == allowedCommands.end()) { // TODO: C++20: replace with contains
qInfo() << command << "command is not one of the whitelisted commands";
reply[QStringLiteral("success")] = false;
return reply;
}
// Make sure command is located in the trusted prefix
QDir prefix = fileInfo.absoluteDir();
QString dirname = prefix.dirName();
if (dirname == QStringLiteral("bin") || dirname == QStringLiteral("sbin")) {
prefix.cdUp();
}
if (trustedPrefixes.find(prefix.path()) == trustedPrefixes.end()) { // TODO: C++20: replace with contains
qInfo() << prefix.path() << "prefix is not one of the trusted command prefixes";
reply[QStringLiteral("success")] = false;
return reply;
}
// connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput);
m_cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } );
m_cmd.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(processChannelMode));
m_cmd.start(command, arguments);
m_cmd.write(input);
m_cmd.closeWriteChannel();
m_cmd.waitForFinished(-1);
QByteArray output = m_cmd.readAllStandardOutput();
reply[QStringLiteral("output")] = output;
reply[QStringLiteral("exitCode")] = m_cmd.exitCode();
QProcess cmd;
cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } );
if((processChannelMode != QProcess::SeparateChannels) && (processChannelMode != QProcess::MergedChannels)) {
return reply;
}
cmd.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(processChannelMode));
cmd.start(command, arguments);
cmd.write(input);
cmd.closeWriteChannel();
cmd.waitForFinished(-1);
QByteArray output = cmd.readAllStandardOutput();
reply[QStringLiteral("output")] = output;
reply[QStringLiteral("exitCode")] = cmd.exitCode();
reply[QStringLiteral("success")] = true;
return reply;
}
@ -316,6 +428,9 @@ bool ExternalCommandHelper::isCallerAuthorized()
// Cache successful authentication requests, so that clients don't need
// to authenticate multiple times during long partitioning operations.
// auth_admin_keep is not used intentionally because with current architecture
// it might lead to data loss if user cancels sfdisk partition boundary adjustment
// after partition data was moved.
if (m_serviceWatcher->watchedServices().contains(message().service())) {
return true;
}

View File

@ -14,12 +14,14 @@
#include <memory>
#include <unordered_set>
#include <QEventLoop>
#include <QString>
#include <QProcess>
#include <QDBusContext>
#include <QEventLoop>
#include <QFile>
#include <QProcess>
#include <QString>
class QDBusServiceWatcher;
constexpr qint64 MiB = 1 << 20;
class ExternalCommandHelper : public QObject, public QDBusContext
{
@ -32,21 +34,21 @@ Q_SIGNALS:
public:
ExternalCommandHelper();
bool readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size);
bool writeData(const QString& targetDevice, const QByteArray& buffer, const qint64 offset);
bool readData(QFile& device, QByteArray& buffer, const qint64 offset, const qint64 size);
bool writeData(QFile& device, const QByteArray& buffer, const qint64 offset);
public Q_SLOTS:
Q_SCRIPTABLE QVariantMap RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
Q_SCRIPTABLE QVariantMap CopyBlocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize);
Q_SCRIPTABLE bool WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte);
Q_SCRIPTABLE bool CreateFile(const QString& filePath, const QByteArray& fileContents);
Q_SCRIPTABLE QVariantMap CopyFileData(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength,
const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize);
Q_SCRIPTABLE QByteArray ReadData(const QString& device, const qint64 offset, const qint64 length);
Q_SCRIPTABLE bool WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetOffset);
Q_SCRIPTABLE bool WriteFstab(const QByteArray& fstabContents);
private:
bool isCallerAuthorized();
void onReadOutput();
QProcess m_cmd;
QDBusServiceWatcher *m_serviceWatcher = nullptr;
};

View File

@ -48,7 +48,7 @@ KAboutData aboutKPMcore()
KAboutData aboutData( QStringLiteral("kpmcore"),
xi18nc("@title", "<application>KPMcore</application>"), QStringLiteral(VERSION),
xi18nc("@title", "Library for managing partitions"),
KAboutLicense::GPL_V3, xi18nc("@info:credit", "&copy; 2008-2020 KPMcore developers" ) );
KAboutLicense::GPL_V3, xi18nc("@info:credit", "&copy; 2008-2022 KPMcore developers" ) );
aboutData.setOrganizationDomain(QByteArray("kde.org"));
aboutData.setProductName(QByteArray("kpmcore"));
aboutData.setHomepage(QStringLiteral("https://commits.kde.org/kpmcore"));

View File

@ -1,14 +0,0 @@
/*
SPDX-FileCopyrightText: 2008 Volker Lanz <vl@fidra.de>
SPDX-FileCopyrightText: 2014-2018 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2015 Chris Campbell <c.j.campbell@ed.ac.uk>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef LIBKPMCORE_EXPORT
#include <QtGlobal>
#define LIBKPMCORE_EXPORT Q_DECL_EXPORT
#endif

View File

@ -1,65 +0,0 @@
[Domain]
Icon=partitionmanager
[org.kde.kpmcore.externalcommand.init]
Name=Start external command daemon
Name[ast]=Aniciu del degorriu de comandos esternos
Name[ca]=Inicia el dimoni d'ordres externes
Name[ca@valencia]=Inicia el dimoni d'ordres externes
Name[cs]=Spustit démona externích příkazů
Name[da]=Start ekstern kommando-dæmon
Name[de]=Externen Befehlsdienst starten
Name[el]=Εκκίνηση διεργασίας με εξωτερική εντολή
Name[en_GB]=Start external command daemon
Name[es]=Iniciar el demonio de órdenes externas
Name[et]=Välise käsu deemoni käivitamine
Name[eu]=Abiarazi kanpoko komandoen daimona
Name[fi]=Käynnistä ulkoinen komentopalvelu
Name[fr]=Lancer le démon de la commande externe
Name[gl]=Iniciar o servizo de orde externa
Name[it]=Avvia demone per comando esterno
Name[ko]=외부 명령 데몬 시작
Name[lt]=Paleisti išorinių komandų tarnybą
Name[nl]=Start externe opdrachtdaemon
Name[pl]=Rozpocznij usługę zewnętrznego polecenia
Name[pt]=Iniciar o servidor de comandos externos
Name[pt_BR]=Iniciar comando externo do daemon
Name[sk]=Spustiť externé démony príkazov
Name[sl]=Zaženite demon za zunanje ukaze
Name[sv]=Starta extern kommandodemon
Name[uk]=Запуск фонової служби зовнішньої команди
Name[x-test]=xxStart external command daemonxx
Name[zh_TW]=啟動外部指令守護程式
Description=Administrative privileges are required to manage disks
Description[ast]=Ríquense los privilexos alministrativos pa xestionar discos
Description[ca]=Es requereixen privilegis d'administrador per a gestionar els discs
Description[ca@valencia]=Es requereixen privilegis d'administrador per a gestionar els discs
Description[cs]=Pro správu disků jsou potřeba práva administrátora
Description[da]=Der kræves administrative rettigheder for at håndtere diske
Description[de]=Systemverwalterrechte sind zur Verwaltung von Festplatten erforderlich
Description[el]=Απαιτούνται δικαιώματα διαχειριστή για τη διαχείριση δίσκων
Description[en_GB]=Administrative privileges are required to manage disks
Description[es]=Se necesitan permisos de administrador para gestionar discos
Description[et]=Ketaste haldamiseks on tarvis administraatori õigusi
Description[eu]=Administrazio pribilegioak behar dira diskoak kudeatzeko
Description[fi]=Levyjen hallinta vaatii pääkäyttäjäoikeuksia
Description[fr]=Vous devez disposer des privilèges d'administrateur pour gérer les disques
Description[gl]=Requírense privilexios de administración para xestionar discos.
Description[it]=Per gestire il disco sono richiesti privilegi di amministratore
Description[ja]=ディスクを管理するには管理者権限が必要です
Description[ko]=디스크를 관리하려면 권한이 필요함
Description[lt]=Diskų tvarkymui reikalingos administratoriaus teisės
Description[nl]=Er zijn administratieve rechten vereist om schijven te beheren
Description[pl]=Do zarządzania dyskami wymagane są uprawnienia administratora
Description[pt]=São necessários privilégios de administrador para gerir os discos
Description[pt_BR]=São necessários privilégios administrativos para gerenciar discos
Description[ru]=Для управления дисками требуются права администратора
Description[sk]=Na správu diskov sa vyžadujú práva správcu
Description[sl]=Za upravljanje diskov so potrebne pravice upravljavca računalnika
Description[sv]=Administratörsprivilegier krävs för att hantera diskar
Description[uk]=Для керування дисками потрібні права доступу адміністратора (root)
Description[x-test]=xxAdministrative privileges are required to manage disksxx
Description[zh_CN]=管理磁盘需要管理权限
Description[zh_TW]=管理硬碟需要管理員權限
Policy=auth_admin
Persistence=session

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: none
SPDX-License-Identifier: CC0-1.0
-->
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<icon_name>partitionmanager</icon_name>
<action id="org.kde.kpmcore.externalcommand.init" >
<description>Run privileged partition manager helper</description>
<description xml:lang="ca">Executa l'ajudant del gestor de particions amb privilegis</description>
<description xml:lang="ca@valencia">Executa l'ajudant del gestor de particions amb privilegis</description>
<description xml:lang="en_GB">Run privileged partition manager helper</description>
<description xml:lang="es">Ejecutar la aplicación auxiliar de gestión de particiones con privilegios</description>
<description xml:lang="fr">Lancer l'assistant de gestionnaire de partition en mode administrateur</description>
<description xml:lang="it">Esegui l'helper per la gestione delle partizioni privilegiate</description>
<description xml:lang="ko">상위 권한으로 파티션 관리자 도우미 실행</description>
<description xml:lang="nl">Hulpprogramma voor partitiebeheerder met extra rechten uitvoeren</description>
<description xml:lang="pl">Uruchom uprzywilejowane zarządzanie partycjami</description>
<description xml:lang="pt">Executar o utilitário privilegiado do gestor de partições</description>
<description xml:lang="pt_BR">Executa o auxiliar do gerenciador de partições com privilégios</description>
<description xml:lang="sl">Zaženi pooblaščenega pomočnika skrbnika particij</description>
<description xml:lang="sv">Kör hjälpverktyg för privilegierad partitionshanterare</description>
<description xml:lang="uk">Запуск привілейованої допоміжної програми з керування розділами</description>
<description xml:lang="zh_CN">使用管理员权限运行分区管理器辅助程序</description>
<message>Administrative privileges are required to manage disks</message>
<message xml:lang="ast">Ríquense los privilexos alministrativos pa xestionar discos</message>
<message xml:lang="ca">Es requereixen privilegis d'administrador per a gestionar els discs</message>
<message xml:lang="ca@valencia">Es requerixen privilegis d'administrador per a gestionar els discs</message>
<message xml:lang="cs">Pro správu disků jsou potřeba práva administrátora</message>
<message xml:lang="de">Systemverwalterrechte sind zur Verwaltung von Festplatten erforderlich</message>
<message xml:lang="el">Απαιτούνται δικαιώματα διαχειριστή για τη διαχείριση των δίσκων</message>
<message xml:lang="en_GB">Administrative privileges are required to manage disks</message>
<message xml:lang="es">Se necesitan permisos de administrador para gestionar discos</message>
<message xml:lang="fr">Vous devez disposer des privilèges d'administrateur pour gérer les disques.</message>
<message xml:lang="hu">A lemzek kezeléséhez adminisztrátori jogosultságok szükségesek</message>
<message xml:lang="it">Per gestire il disco sono richiesti privilegi amministrativi</message>
<message xml:lang="ko">디스크를 관리하려면 권한이 필요함</message>
<message xml:lang="lt">Diskų tvarkymui reikalingos administratoriaus teisės</message>
<message xml:lang="nl">Er zijn administratieve rechten vereist om schijven te beheren</message>
<message xml:lang="pl">Do zarządzania dyskami wymagane są uprawnienia administratora</message>
<message xml:lang="pt">São necessários privilégios de administração para gerir os discos</message>
<message xml:lang="pt_BR">São necessários privilégios administrativos para gerenciar discos</message>
<message xml:lang="sk">Na správu diskov sa vyžadujú oprávnenia správcu</message>
<message xml:lang="sl">Za upravljanje diskov so potrebne pravice upravljavca računalnika</message>
<message xml:lang="sv">Administratörsprivilegier krävs för att hantera diskar</message>
<message xml:lang="uk">Для керування дисками потрібні права доступу адміністратора (root)</message>
<message xml:lang="zh_CN">管理磁盘需要管理员权限</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -36,7 +36,7 @@ class LIBKPMCORE_EXPORT Report : public QObject
public:
explicit Report(Report* p, const QString& cmd = QString());
~Report();
~Report() override;
Q_SIGNALS:
void outputChanged();

2
src/util/trustedprefixes Normal file
View File

@ -0,0 +1,2 @@
/
/usr

View File

@ -14,7 +14,6 @@ set(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
include_directories(${CMAKE_SOURCE_DIR}/src) # To get at KPMcore headers
add_compile_options(-fPIC)
###
@ -23,11 +22,11 @@ add_compile_options(-fPIC)
# and to add a test with the given name.
#
add_library(testhelpers STATIC helpers.cpp)
target_link_libraries(testhelpers)
target_link_libraries(testhelpers PRIVATE kpmcore)
macro (kpm_test name)
add_executable(${name} ${ARGN})
target_link_libraries(${name} testhelpers kpmcore Qt5::Core)
target_link_libraries(${name} testhelpers kpmcore Qt${QT_MAJOR_VERSION}::Core)
endmacro()
###
@ -35,15 +34,15 @@ endmacro()
# Tests of initialization: try explicitly loading some backends
kpm_test(testinit testinit.cpp) # Default backend
if(TARGET pmdummybackendplugin)
add_test(NAME testinit-dummy COMMAND testinit $<TARGET_FILE:pmdummybackendplugin>)
add_test(NAME testinit-dummy COMMAND testinit $<TARGET_FILE_NAME:pmdummybackendplugin>)
endif()
if(TARGET pmsfdiskbackendplugin)
add_test(NAME testinit-sfdisk COMMAND testinit $<TARGET_FILE:pmsfdiskbackendplugin>)
add_test(NAME testinit-sfdisk COMMAND testinit $<TARGET_FILE_NAME:pmsfdiskbackendplugin>)
else()
return() # All the rest really needs a working backend
endif()
set(BACKEND $<TARGET_FILE:pmsfdiskbackendplugin>)
set(BACKEND $<TARGET_FILE_NAME:pmsfdiskbackendplugin>)
###
#