* 'chs' of https://github.com/pali/util-linux:
fdisk: Add support for fixing MBR partitions CHS values
libfdisk: (dos) Add function fdisk_dos_fix_chs() for fixing CHS values for all partitions
libfdisk: (dos) Add function dos_partition_sync_chs() for updating CHS values
This function fixes beginning and ending CHS values for every partition
according to LBA relative offset, relative beginning and size and fdisk
idea of disk geometry (sectors per track and number of heads). This
function may be used for repairing existing partitions to be compatible
with CHS addressing.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Call this function everytime after changing either relative LBA partition
offset or LBA partition size to ensure that CHS values are in sync with
LBA.
This should fix partition CHS values after moving or deleting partition.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Since libblkid commit 751eca28fc it does
not ignore FAT on whole-disks, so now libfdisk sees collision between
FAT and MBR. It's fine to report the collision to users, but we should
not ignore the MBR.
Signed-off-by: Karel Zak <kzak@redhat.com>
Current algorithm implemented in get_partition_table_geometry() function
is wrong. It take head bits from CHS position from the end of the last
partition and proclaim that this value is number of heads on disk. Same
does for sectors bits from CHS and proclaim that this value is number of
sectors per tracks. As number of disk heads and head bits in CHS position
are different things this just results in bogus detected disk geometry.
Implement a new algorithm to determinate number of heads and sectors per
track from partition sector offsets. In MBR table for every partition is
stored every sector offset in two formats: one as CHS and one as LBA.
Conversion from CHS to LBA is defined by formula:
LBA = (c * N_heads + h) * N_sectors + (s - 1)
So if we have two different offsets in both CHS and LBA formats, written as
(LBA1, c1, h1, s1) and (LBA2, c2, h2, s2) then we can calculate number of
heads and sectors per tracks by solving linear equations as:
N_heads = (o1 * h2 - o2 * h1) / (o2 * c1 - o1 * c2)
N_sectors = (o2 * c1 - o1 * c2) / (c1 * h2 - c2 * h1)
where
o = LBA - (s - 1)
Integer division also verifies that offsets were calculated from same
number of heads and sectors per track as division must be always positive
with no reminder.
There is a special case when either numerator or denominator is zero. This
indicates that comparing partition offsets have also same CHS offset
divisor which leads to fact that calculation of number of heads and sector
per tracks is not possible.
In MBR table are stored up to 8 offset numbers, so it means there are up
to the 28 of candidates which can expose number of disk heads and number of
disk sectors per track. Start with offsets which belongs to same partition
and start from the first partition. As the first partition in most cases
was used by BIOS for booting.
It is required to skip CHS values 1023/254/63 and 1023/255/63 as these
indicates that values are invalid or overflowed.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
To determinate if CHS values are valid for consistency check and not
overflowed, it is needed to check current CHS cylinder value and not total
disk cylinder values. It is possible that also on "big" disk there is first
small partition which can be represented by CHS tuple.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
To check if LBA sector can be represented in CHS without overflow it is
required to check for cylinder value which belongs to the LBA sector. And
not the total number of disk cylinders. Note that maximal representable
total number of disk cylinders is 1024 and therefore the last cylinder
which which can be stored in CHS tuple is 1023. Hence strict inequality is
used.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
It does not matter if dos compatibility flag is turned on or off. CHS
values in partition entry can overflow also when dos compatibility flag is
turned off. In this case maximal representable CHS values should be used.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Function check_consistency() prints errors to console output but does not
calculate correct error numbers in summary error message. Fix it, so fdisk
prints correct number in summary message "N errors detected.".
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
There is no reason to check only end CHS partition parameters. Check also
begin values and correctly count errors in nerrors variable. fdisk then
print correctly summary message "N errors detected.".
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Function check() checks that LBA addresses sector number matches CHS sector
number. But error message contains information about "previous sectors" and
"total sectors" which is misleading so change it.
Also rename variables 'start' and 'total' to make it clear what value is
stored in them. Note that in 'start' variable is currently stored last LBA
partition sector and in 'total' is stored last CHS partition sector. So
neither sector where partition starts nor total sectors of partition.
Code and check logic looks to be correct, just error message and variable
names are misleading. Therefore no functional changes in this patch.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Number of CHS sectors (indexed from zero) is stored in variable 'real_s'.
In variable 's' is stored in high 2 bits number of CHS cylinders.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
After geometry is changes it is required to recalculate total number of
cylinders. Otherwise total disk capacity is either reduced or extended.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
The function fdisk_reorder_partitions() is also used in sfdisk and cfdisk
and these commands assume info/warn messages from the library. So move all
messages from fdisk to fdisk_reorder_partitions().
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Option 'f' currently prints following RED error message:
Nothing to do. Ordering is correct already.
Failed to fix partitions order.
This change removes RED error message when ordering is already correct.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
The code should be able to keep track about previous content and print
JSON objects separator automatically.
Signed-off-by: Karel Zak <kzak@redhat.com>
Otherwise, sfdisk would error out on its own dump, as first-lba would be
earlier than "plausible" assuming the default table size.
This is because it did not look for `table-length` when using an sfdisk
script. This means that using `--dump` on a valid image, could not be
unserialized back into a valid image.
This is helpful in exotic situations, where a partition has to be
created earlier than the conventional "first-lba" (2048). For example,
on Allwinner A64 boards, where a firmware is stored at LBA16. With this
it is possible to ask for `first-lba` at or earlier than 16, by reducing
the number of entries to e.g. 48.
It's seems detection by BLKRRPART is broken in recent kernels
(probably regression), and it's also overkill to force kernel re-read
all and generate all the events. It seems more elegant to use O_EXCL.
Signed-off-by: Karel Zak <kzak@redhat.com>
The whole thing is complicated by the fact that we have two layers
of libraries: e.g. libmount also needs libblkid. If we just tell meson
to make libmount static, this is not enough, because we also need it
to link to a static libblkid. Hence in the case of libs that link to
other libs internally, we need to create a different object with a
a different set of link_with items.
To avoid building the libraries twice, libfdisk and libmount are first
built into an internal "convenience" library, which is then linked into
the static and shared versions as appropriate.
To build: meson build && ninja -C build
To run tests: ninja -C build check
To install for packaging: DESTDIR=/var/tmp/inst ninja -C build install
To install for realz: sudo ninja -C build install
v2:
- Optional items are now based on the 'feature' feature in meson.
Built libraries which are disabled turn into disabler() objects
and also poison any executables which link to them.
What is there:
- building of the binaries and libs and the python module
- installation of binaries, libs, python module, localization files,
man pages, pkgconfig files
- running of tests
- most options to configure build equivalently to the
./configure settings
Partially implemented:
- disabling of stuff when things missing. In the C code, the defines
are all used, so that should be fine. In the build system, some
files should be skipped, but that is probably not always done properly.
Getting this right might require some testing of various build option
combinations to get the details right.
Not implemented:
- static builds of fdisk and other binaries
- things marked with XXX or FIXME
- ???
Differences:
- .la files are not created. They are useless and everybody hates them.
- Requires.private in pkgconfig files are not present in the
autogenerated .pc file. Not sure if they should be there or not. If
necessary, they can be added by hand.
- man pages and systemd units are installed by the install target. Not
sure why 'make install' doesn't do that.
- the split between / and /usr is probably wrong. But it's all pointless
anyway, so maybe we could simplify things but not implementing it at
all under meson?
* rename 'last' to 'first' as we use this value as the first available free
sector rather than last used
* use '-1' when calculate last partition sector to compare with last
disk sector
* improve debug messages
Fixes: https://github.com/karelzak/util-linux/issues/1249
Signed-off-by: Karel Zak <kzak@redhat.com>
All `eject` tests were failing under ASan, since they call /bin/mount,
which is uninstrumented, but it picks up the instrumented `libblkid`
library, causing ASan to complain:
gcc:
ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
eject: unmount of `/home/runner/work/util-linux/util-linux/tests/output/eject/umount-by-disk-mounted-mnt' failed
clang:
/bin/umount: symbol lookup error: /home/runner/work/util-linux/util-linux/.libs/libblkid.so.1: undefined symbol: __sancov_lowest_stack
eject: unmount of `/home/runner/work/util-linux/util-linux/tests/output/eject/umount-by-disk-mounted-mnt' failed
Subsequently, all tests which require the `scsi_debug` module get skipped,
since it's still in use due to the failed umount:
fdisk: align 512/4K ... SKIPPED (cannot remove scsi_debug module (rmmod))
fdisk: align 512/4K +alignment_offset ... SKIPPED (cannot remove scsi_debug module (rmmod))
fdisk: align 512/4K +MD ... SKIPPED (cannot remove scsi_debug module (rmmod))
In case of gcc this can be easily resolved by setting $LD_PRELOAD to the
respective ASan library. clang makes this a bit more difficult, since it
compiles the ASan library statically, so firstly we need to force dynamic
linking (via -shared-asan), and then add the runtime DSO path to the
linker cache, since it's in a non-standard path.
A 33553920 byte optimal I/O size arises from badly-implemented USB SATA
adapters reporting 0xffff 512 byte sectors (32 MiB - 512). Commit
acb7651f88 indirectly addresses this by
ignoring the optimal I/O size if it's not a multiple of the physical
sector size. That works if the physical sector size is 4096, but
33553920 optimal is allowed for 512 physical.
This commit explicitly ignores 33553920, as there is no legitimate
situation where this number would be the real optimal I/O size.
Signed-off-by: Ryan Finnie <ryan@finnie.org>
Closes: https://github.com/karelzak/util-linux/issues/1221
- use robust functions like write_all()
- don't use assert() to check write/open/etc return values, because oss-fuzz.com
report foreign (system, libc, ...) issues as our fails
Addresses: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28009
Signed-off-by: Karel Zak <kzak@redhat.com>
The default is 128 partitions (entries in partitions array). The size
of the entry is 128 bytes, it means 32 sectors (512-byte) for the
array. The default is too large for tiny devices and it seems better to
dynamically reduce the number to fix the device size.
The reduction is reported to user.
Example:
$ dd if=/dev/zero of=8-sectors.img count=8 bs=512
$ fdisk 8-sectors.img
...
Command (m for help): g
Created a new GPT disklabel (GUID: 3DB3EECE-BCCA-6C46-95FA-7E23783BB3B2).
The maximal number of partitions is 8 (default is 128).
Command (m for help): x
Expert command (m for help): p
Disk 8-sectors.img: 4 KiB, 4096 bytes, 8 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 3DB3EECE-BCCA-6C46-95FA-7E23783BB3B2
First LBA: 4
Last LBA: 4
Alternative LBA: 7
Partition entries LBA: 2
Allocated partition entries: 8
In this case, sectors:
0 - PMBR
1 - GPT header
2-3 - GPT array of partitions (8 entries, 128 bytes each)
4 - partition data
5-6 - backup GPT array of partitions
7 - backup GPT header
The smallest image is 6 sectors with 4 entries in array of partitions.
Note that Linux kernel has no problem to accept 4K image with 1
512-bytes GPT partition.
# losetup -P -f 4K.img
# lsblk /dev/loop0
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 4K 0 loop
└─loop0p1 259:5 0 512B 0 part
... but we need to fix libblkid, it ignores so small devices to probe for GPT :)
Addresses: https://github.com/karelzak/util-linux/issues/1147
Signed-off-by: Karel Zak <kzak@redhat.com>
The current code creates GPT header and partitions arrays (with 128
entries ...) although there is no space for all the stuff. This patch
forces fdisk_create_disklabel() to return -ENOSPC if the last and first
usable LBA calculation is out of device size.
Addresses: https://github.com/karelzak/util-linux/issues/1147
Signed-off-by: Karel Zak <kzak@redhat.com>
When the partition table is present **but** empty, the existing code would output fields followed by a `,` , on the assumption that the list of partitions would follow. But if the list of partitions is empty, it is skipped, leading to output like this:
```
{
"partitiontable": {
"label":"gpt",
"id":"1F9E80D9-DD78-024F-94A3-B61EC82B18C8",
"device":"/dev/sdb",
"unit":"sectors",
"firstlba":2048,
"lastlba":30949342,
"sectorsize":512,
}
}
```
Note the `512,` on the *sectorsize* line.
This is invalid JSON for some parsers, which choke on it.
Avoid this, by checking when outputting the last separator: if there's no table, or there is a table but it is empty, then just put a newline, otherwise use the old path of comma-newline and assume there's going to be a list of partitions after.