libblkid: improve handling of ISO files with partition tables
The ISO format specifically leaves the first 32kb blank so that it can be used for other purposes, such as adding a partition table. This is commonly used (e.g. by Endless and Fedora installation media) to have partition 0 starting at sector 0 as a mountable iso9660 filesystem, followed by more partitions (e.g. an EFI system partition). Such layouts can be easily created by tools such as xorriso. When plugging in a USB disk flashed with this type of ISO, blkid presents a somewhat confusing view of the block devices. Taking the example of a 'sda' disk with two partitions: 1. The "iso partition" 2. An unformatted partition In such a setup, before the changes here, blkid will currently report the ISO metadata attributes ID_FS_PUBLISHER_ID, ID_FS_UUID, ID_FS_LABEL, and ID_FS_TYPE=iso9660 on both sda *and* sda1. Since sda2 is unformatted, it won't have any ID_FS_ attributes of it's own. And due to the following standard udev rule: # for partitions import parent information ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*" sda2 will actually import all of the ID_FS_ stuff from the parent device sda. The result at this point is that three udev devices all have the same ID_FS_ attribute values, leading to strange results such as three devices all racing to own the link in /dev/disk/by-uuid, so you can't reliably do a mount-by-UUID. Clean up this situation by detecting such partitioned ISO disks in the superblock probing setup. If files of this kind are detected, we now only expose the ISO metadata attributes on the specific partition that points to the ISO data (and not the parent disk). Signed-off-by: Daniel Drake <drake@endlessm.com>
This commit is contained in:
parent
775022bdd7
commit
7ef86a0891
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -165,6 +166,37 @@ static int is_str_empty(const unsigned char *str, size_t len)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ISO format specifically avoids the first 32kb to allow for a
|
||||||
|
* partition table to be added, if desired.
|
||||||
|
* When an ISO contains a partition table, the usual thing to do is to
|
||||||
|
* have a partition that points at the iso filesystem. In such case,
|
||||||
|
* we want to only probe the iso metadata for the corresponding partition
|
||||||
|
* device, avoiding returning the metadata for the parent block device.
|
||||||
|
*/
|
||||||
|
static bool isofs_belongs_to_device(blkid_probe pr)
|
||||||
|
{
|
||||||
|
dev_t devno;
|
||||||
|
blkid_partlist ls;
|
||||||
|
|
||||||
|
/* Get device number, but if that fails, assume we aren't dealing
|
||||||
|
* with partitions, and continue probing. */
|
||||||
|
devno = blkid_probe_get_devno(pr);
|
||||||
|
if (!devno)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Get partition table, but if that fails, assume we aren't dealing
|
||||||
|
* with partitions, and continue probing. */
|
||||||
|
ls = blkid_probe_get_partitions(pr);
|
||||||
|
if (!ls)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Check that the device we're working with corresponds to an
|
||||||
|
* entry in the partition table. If so, this is the correct
|
||||||
|
* device to return the iso metadata on. */
|
||||||
|
return blkid_partlist_devno_to_partition(ls, devno) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* iso9660 [+ Microsoft Joliet Extension] */
|
/* iso9660 [+ Microsoft Joliet Extension] */
|
||||||
static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
|
static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
|
||||||
{
|
{
|
||||||
|
@ -180,6 +212,11 @@ static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
|
||||||
if (!iso)
|
if (!iso)
|
||||||
return errno ? -errno : 1;
|
return errno ? -errno : 1;
|
||||||
|
|
||||||
|
/* Check if the iso metadata should be returned on a different device
|
||||||
|
* instead of this one. */
|
||||||
|
if (!isofs_belongs_to_device(pr))
|
||||||
|
return 1;
|
||||||
|
|
||||||
memcpy(label, iso->volume_id, sizeof(label));
|
memcpy(label, iso->volume_id, sizeof(label));
|
||||||
|
|
||||||
blkid_probe_set_block_size(pr, 2048);
|
blkid_probe_set_block_size(pr, 2048);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
ID_FS_BLOCK_SIZE=2048
|
||||||
|
ID_FS_PUBLISHER_ID=UTIL-LINUX
|
||||||
|
ID_FS_UUID=2019-09-24-09-31-05-00
|
||||||
|
ID_FS_UUID_ENC=2019-09-24-09-31-05-00
|
||||||
|
ID_FS_VERSION=Joliet\x20Extension
|
||||||
|
ID_FS_LABEL=ISOIMAGE
|
||||||
|
ID_FS_LABEL_ENC=ISOIMAGE
|
||||||
|
ID_FS_TYPE=iso9660
|
||||||
|
ID_FS_USAGE=filesystem
|
|
@ -0,0 +1,25 @@
|
||||||
|
ID_PART_TABLE_TYPE=dos
|
||||||
|
--
|
||||||
|
ID_FS_BLOCK_SIZE=2048
|
||||||
|
ID_FS_PUBLISHER_ID=UTIL-LINUX
|
||||||
|
ID_FS_UUID=2019-09-24-09-31-05-00
|
||||||
|
ID_FS_UUID_ENC=2019-09-24-09-31-05-00
|
||||||
|
ID_FS_VERSION=Joliet\x20Extension
|
||||||
|
ID_FS_LABEL=ISOIMAGE
|
||||||
|
ID_FS_LABEL_ENC=ISOIMAGE
|
||||||
|
ID_FS_TYPE=iso9660
|
||||||
|
ID_FS_USAGE=filesystem
|
||||||
|
ID_PART_TABLE_TYPE=dos
|
||||||
|
ID_PART_ENTRY_SCHEME=dos
|
||||||
|
ID_PART_ENTRY_TYPE=0x83
|
||||||
|
ID_PART_ENTRY_NUMBER=1
|
||||||
|
ID_PART_ENTRY_OFFSET=0
|
||||||
|
ID_PART_ENTRY_SIZE=136
|
||||||
|
ID_PART_ENTRY_DISK=__ts_majorminor__
|
||||||
|
--
|
||||||
|
ID_PART_ENTRY_SCHEME=dos
|
||||||
|
ID_PART_ENTRY_TYPE=0xef
|
||||||
|
ID_PART_ENTRY_NUMBER=2
|
||||||
|
ID_PART_ENTRY_OFFSET=136
|
||||||
|
ID_PART_ENTRY_SIZE=4096
|
||||||
|
ID_PART_ENTRY_DISK=__ts_majorminor__
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 Endless Mobile, Inc.
|
||||||
|
#
|
||||||
|
# This file is part of util-linux.
|
||||||
|
#
|
||||||
|
# This file is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This file is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
|
||||||
|
TS_TOPDIR="${0%/*}/../.."
|
||||||
|
TS_DESC="iso-partitions"
|
||||||
|
|
||||||
|
. $TS_TOPDIR/functions.sh
|
||||||
|
|
||||||
|
ts_init "$*"
|
||||||
|
|
||||||
|
ts_check_test_command "$TS_CMD_BLKID"
|
||||||
|
ts_check_test_command "$TS_CMD_PARTX"
|
||||||
|
|
||||||
|
ts_skip_nonroot
|
||||||
|
|
||||||
|
# set global variable TS_DEVICE
|
||||||
|
ts_scsi_debug_init dev_size_mb=50
|
||||||
|
|
||||||
|
# This image (created by xorriso) has partition 1 pointing to the ISO
|
||||||
|
# area, followed by an unformatted second partition.
|
||||||
|
xz -dc ${TS_SELF}/iso-partitions.img.xz > ${TS_DEVICE}
|
||||||
|
udevadm settle
|
||||||
|
|
||||||
|
ts_init_subtest "partitions"
|
||||||
|
$TS_CMD_PARTX -a ${TS_DEVICE} &>/dev/null
|
||||||
|
udevadm settle
|
||||||
|
|
||||||
|
# Check that the ISO metadata is not shown on the main disk device
|
||||||
|
$TS_CMD_BLKID -p -o udev ${TS_DEVICE} >> $TS_OUTPUT
|
||||||
|
echo -- >> $TS_OUTPUT
|
||||||
|
|
||||||
|
# Check that the ISO metadata is shown on the "ISO partition"
|
||||||
|
$TS_CMD_BLKID -p -o udev ${TS_DEVICE}1 >> $TS_OUTPUT
|
||||||
|
echo -- >> $TS_OUTPUT
|
||||||
|
|
||||||
|
# Check that the ISO metadata is not shown on the other partition
|
||||||
|
$TS_CMD_BLKID -p -o udev ${TS_DEVICE}2 >> $TS_OUTPUT
|
||||||
|
|
||||||
|
# substitute major/minor number before comparison
|
||||||
|
sed -i \
|
||||||
|
-e 's/^\(ID_PART_ENTRY_DISK\)=.*/\1=__ts_majorminor__/' \
|
||||||
|
$TS_OUTPUT
|
||||||
|
|
||||||
|
ts_finalize_subtest
|
||||||
|
|
||||||
|
# Remove the partition table and check that the ISO metadata is shown on the
|
||||||
|
# main disk device.
|
||||||
|
ts_init_subtest "no_partitions"
|
||||||
|
dd if=/dev/zero of=${TS_DEVICE} bs=512 count=1 &>/dev/null
|
||||||
|
udevadm settle
|
||||||
|
$TS_CMD_PARTX -d ${TS_DEVICE} &>/dev/null
|
||||||
|
udevadm settle
|
||||||
|
$TS_CMD_BLKID -p -o udev ${TS_DEVICE} >> $TS_OUTPUT
|
||||||
|
ts_finalize_subtest
|
||||||
|
|
||||||
|
ts_finalize
|
Binary file not shown.
Loading…
Reference in New Issue