]> git.pld-linux.org Git - packages/parted.git/blame - 0099-libparted-Add-support-for-MBR-id-GPT-GUID-and-detect.patch
- release 6 (by relup.sh)
[packages/parted.git] / 0099-libparted-Add-support-for-MBR-id-GPT-GUID-and-detect.patch
CommitLineData
74a816df
MK
1From 8740cfcff3ea839dd6dc8650dec0a466e9870625 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.rohar@gmail.com>
3Date: Tue, 28 Aug 2018 21:20:01 +0200
4Subject: [PATCH 099/103] libparted: Add support for MBR id, GPT GUID and
5 detection of UDF filesystem
6
7This is needed for libparted based applications (like Gparted) to correctly
8choose MBR id and GPT GUID for UDF filesystem. MBR id for UDF is 0x07 and
9GPT GUID is Microsoft Basic Data, see why: https://serverfault.com/a/829172
10
11Without registering a new libparted fs code it is not possible to assign
12MBR id or GPT GUID.
13
14Detection of UDF filesystem is done by checking presence of UDF VSD (NSR02
15or NSR03 identifier) and UDF AVDP at expected locations (blocks 256, -257,
16-1, 512).
17
18Signed-off-by: Brian C. Lane <bcl@redhat.com>
19---
20 NEWS | 2 +
21 libparted/fs/Makefile.am | 1 +
22 libparted/fs/udf/udf.c | 175 ++++++++++++++++++++++++++
23 libparted/labels/dos.c | 3 +
24 libparted/labels/gpt.c | 1 +
25 libparted/libparted.c | 4 +
26 scripts/data/abi/baseline_symbols.txt | 2 +
27 tests/Makefile.am | 1 +
28 tests/t2410-dos-udf-partition-type.sh | 38 ++++++
29 9 files changed, 227 insertions(+)
30 create mode 100644 libparted/fs/udf/udf.c
31 create mode 100644 tests/t2410-dos-udf-partition-type.sh
32
33diff --git a/NEWS b/NEWS
34index ee6efb6..45ea91c 100644
35--- a/NEWS
36+++ b/NEWS
37@@ -47,6 +47,8 @@ GNU parted NEWS -*- outline -*-
38
39 ** New Features
40
41+ Add support for MBR id, GPT GUID and detection of UDF filesystem.
42+
43 libparted-fs-resize: Work on non 512 byte sectors.
44
45 Add resizepart command to resize a partition. This works even on
46diff --git a/libparted/fs/Makefile.am b/libparted/fs/Makefile.am
47index d3cc8bc..cab32c7 100644
48--- a/libparted/fs/Makefile.am
49+++ b/libparted/fs/Makefile.am
50@@ -44,6 +44,7 @@ libfs_la_SOURCES = \
51 ntfs/ntfs.c \
52 reiserfs/reiserfs.c \
53 reiserfs/reiserfs.h \
54+ udf/udf.c \
55 ufs/ufs.c \
56 xfs/platform_defs.h \
57 xfs/xfs.c \
58diff --git a/libparted/fs/udf/udf.c b/libparted/fs/udf/udf.c
59new file mode 100644
60index 0000000..00209e1
61--- /dev/null
62+++ b/libparted/fs/udf/udf.c
63@@ -0,0 +1,175 @@
64+/*
65+ libparted - a library for manipulating disk partitions
66+ Copyright (C) 2018 Free Software Foundation, Inc.
67+
68+ This program is free software; you can redistribute it and/or modify
69+ it under the terms of the GNU General Public License as published by
70+ the Free Software Foundation; either version 3 of the License, or
71+ (at your option) any later version.
72+
73+ This program is distributed in the hope that it will be useful,
74+ but WITHOUT ANY WARRANTY; without even the implied warranty of
75+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
76+ GNU General Public License for more details.
77+
78+ You should have received a copy of the GNU General Public License
79+ along with this program. If not, see <http://www.gnu.org/licenses/>.
80+*/
81+
82+#include <config.h>
83+
84+#include <parted/parted.h>
85+
86+/* Read bytes using ped_geometry_read() function */
87+static int read_bytes (const PedGeometry* geom, void* buffer, PedSector offset, PedSector count)
88+{
89+ char* sector_buffer;
90+ PedSector sector_offset, sector_count, buffer_offset;
91+
92+ sector_offset = offset / geom->dev->sector_size;
93+ sector_count = (offset + count + geom->dev->sector_size - 1) / geom->dev->sector_size - sector_offset;
94+ buffer_offset = offset - sector_offset * geom->dev->sector_size;
95+
96+ sector_buffer = alloca (sector_count * geom->dev->sector_size);
97+
98+ if (!ped_geometry_read (geom, sector_buffer, sector_offset, sector_count))
99+ return 0;
100+
101+ memcpy (buffer, sector_buffer + buffer_offset, count);
102+ return 1;
103+}
104+
105+/* Scan VSR and check for UDF VSD */
106+static int check_vrs (const PedGeometry* geom, unsigned int vsdsize)
107+{
108+ PedSector block;
109+ PedSector offset;
110+ unsigned char ident[5];
111+
112+ /* Check only first 64 blocks, but theoretically standard does not define upper limit */
113+ for (block = 0; block < 64; block++) {
114+ /* VRS starts at fixed offset 32kB, it is independent of block size or vsd size */
115+ offset = 32768 + block * vsdsize;
116+
117+ /* Read VSD identifier, it is at offset 1 */
118+ if (!read_bytes (geom, ident, offset + 1, 5))
119+ return 0;
120+
121+ /* Check for UDF identifier */
122+ if (memcmp (ident, "NSR02", 5) == 0 ||
123+ memcmp (ident, "NSR03", 5) == 0)
124+ return 1;
125+
126+ /* Unknown VSD identifier means end of VRS */
127+ if (memcmp (ident, "BEA01", 5) != 0 &&
128+ memcmp (ident, "TEA01", 5) != 0 &&
129+ memcmp (ident, "BOOT2", 5) != 0 &&
130+ memcmp (ident, "CD001", 5) != 0 &&
131+ memcmp (ident, "CDW02", 5) != 0)
132+ break;
133+ }
134+
135+ return 0;
136+}
137+
138+/* Check for UDF AVDP */
139+static int check_anchor (const PedGeometry* geom, unsigned int blocksize, int rel_block)
140+{
141+ PedSector block;
142+ unsigned char tag[16];
143+
144+ /* Negative block means relative to the end of device */
145+ if (rel_block < 0) {
146+ block = geom->length * geom->dev->sector_size / blocksize;
147+ if (block <= (PedSector)(-rel_block))
148+ return 0;
149+ block -= (PedSector)(-rel_block);
150+ if (block < 257)
151+ return 0;
152+ } else {
153+ block = rel_block;
154+ }
155+
156+ if (!read_bytes (geom, tag, block * blocksize, 16))
157+ return 0;
158+
159+ /* Check for AVDP type (0x0002) */
160+ if (((unsigned short)tag[0] | ((unsigned short)tag[1] << 8)) != 0x0002)
161+ return 0;
162+
163+ /* Check that location stored in AVDP matches */
164+ if (((unsigned long)tag[12] | ((unsigned long)tag[13] << 8) | ((unsigned long)tag[14] << 16) | ((unsigned long)tag[15] << 24)) != block)
165+ return 0;
166+
167+ return 1;
168+}
169+
170+/* Detect presence of UDF AVDP */
171+static int detect_anchor(const PedGeometry* geom, unsigned int blocksize)
172+{
173+ /* All possible AVDP locations in preferred order */
174+ static int anchors[] = { 256, -257, -1, 512 };
175+ size_t i;
176+
177+ for (i = 0; i < sizeof (anchors)/sizeof (*anchors); i++) {
178+ if (check_anchor (geom, blocksize, anchors[i]))
179+ return 1;
180+ }
181+
182+ return 0;
183+}
184+
185+/* Detect UDF filesystem, it must have VRS and AVDP */
186+static int detect_udf (const PedGeometry* geom)
187+{
188+ unsigned int blocksize;
189+
190+ /* VSD size is min(2048, UDF block size), check for block sizes <= 2048 */
191+ if (check_vrs (geom, 2048)) {
192+ for (blocksize = 512; blocksize <= 2048; blocksize *= 2) {
193+ if (detect_anchor (geom, blocksize))
194+ return 1;
195+ }
196+ }
197+
198+ /* Check for block sizes larger then 2048, maximal theoretical block size is 32kB */
199+ for (blocksize = 4096; blocksize <= 32768; blocksize *= 2) {
200+ if (!check_vrs (geom, blocksize))
201+ continue;
202+ if (detect_anchor (geom, blocksize))
203+ return 1;
204+ }
205+
206+ return 0;
207+}
208+
209+PedGeometry*
210+udf_probe (PedGeometry* geom)
211+{
212+ if (!detect_udf (geom))
213+ return NULL;
214+
215+ return ped_geometry_duplicate (geom);
216+}
217+
218+static PedFileSystemOps udf_ops = {
219+ probe: udf_probe,
220+};
221+
222+static PedFileSystemType udf_type = {
223+ next: NULL,
224+ ops: &udf_ops,
225+ name: "udf",
226+};
227+
228+void
229+ped_file_system_udf_init ()
230+{
231+ ped_file_system_type_register (&udf_type);
232+}
233+
234+void
235+ped_file_system_udf_done ()
236+{
237+ ped_file_system_type_unregister (&udf_type);
238+}
239diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c
240index fa53020..b2b8de9 100644
241--- a/libparted/labels/dos.c
242+++ b/libparted/labels/dos.c
243@@ -65,6 +65,7 @@ static const char MBR_BOOT_CODE[] = {
244 #define PARTITION_FAT16 0x06
245 #define PARTITION_NTFS 0x07
246 #define PARTITION_HPFS 0x07
247+#define PARTITION_UDF 0x07
248 #define PARTITION_FAT32 0x0b
249 #define PARTITION_FAT32_LBA 0x0c
250 #define PARTITION_FAT16_LBA 0x0e
251@@ -1498,6 +1499,8 @@ msdos_partition_set_system (PedPartition* part,
252 } else if (!strcmp (fs_type->name, "hfs")
253 || !strcmp (fs_type->name, "hfs+"))
254 dos_data->system = PARTITION_HFS;
255+ else if (!strcmp (fs_type->name, "udf"))
256+ dos_data->system = PARTITION_UDF;
257 else if (!strcmp (fs_type->name, "sun-ufs"))
258 dos_data->system = PARTITION_SUN_UFS;
259 else if (is_linux_swap (fs_type->name))
260diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
261index 6f92a34..860f415 100644
262--- a/libparted/labels/gpt.c
263+++ b/libparted/labels/gpt.c
264@@ -1513,6 +1513,7 @@ gpt_partition_set_system (PedPartition *part,
265 if (fs_type)
266 {
267 if (strncmp (fs_type->name, "fat", 3) == 0
268+ || strcmp (fs_type->name, "udf") == 0
269 || strcmp (fs_type->name, "ntfs") == 0)
270 {
271 gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
272diff --git a/libparted/libparted.c b/libparted/libparted.c
273index 3bd071d..e517875 100644
274--- a/libparted/libparted.c
275+++ b/libparted/libparted.c
276@@ -112,6 +112,7 @@ extern void ped_file_system_fat_init (void);
277 extern void ped_file_system_ext2_init (void);
278 extern void ped_file_system_nilfs2_init (void);
279 extern void ped_file_system_btrfs_init (void);
280+extern void ped_file_system_udf_init (void);
281
282 static void
283 init_file_system_types ()
284@@ -128,6 +129,7 @@ init_file_system_types ()
285 ped_file_system_ext2_init ();
286 ped_file_system_nilfs2_init ();
287 ped_file_system_btrfs_init ();
288+ ped_file_system_udf_init ();
289 }
290
291 extern void ped_disk_aix_done ();
292@@ -193,6 +195,7 @@ extern void ped_file_system_ufs_done (void);
293 extern void ped_file_system_xfs_done (void);
294 extern void ped_file_system_amiga_done (void);
295 extern void ped_file_system_btrfs_done (void);
296+extern void ped_file_system_udf_done (void);
297
298 static void
299 done_file_system_types ()
300@@ -209,6 +212,7 @@ done_file_system_types ()
301 ped_file_system_xfs_done ();
302 ped_file_system_amiga_done ();
303 ped_file_system_btrfs_done ();
304+ ped_file_system_udf_done ();
305 }
306
307 static void _done() __attribute__ ((destructor));
308diff --git a/scripts/data/abi/baseline_symbols.txt b/scripts/data/abi/baseline_symbols.txt
309index 9162f1a..69abd82 100644
310--- a/scripts/data/abi/baseline_symbols.txt
311+++ b/scripts/data/abi/baseline_symbols.txt
312@@ -340,6 +340,8 @@ FUNC:ped_file_system_type_get
313 FUNC:ped_file_system_type_get_next
314 FUNC:ped_file_system_type_register
315 FUNC:ped_file_system_type_unregister
316+FUNC:ped_file_system_udf_init
317+FUNC:ped_file_system_udf_done
318 FUNC:ped_file_system_ufs_done
319 FUNC:ped_file_system_ufs_init
320 FUNC:ped_file_system_xfs_done
321diff --git a/tests/Makefile.am b/tests/Makefile.am
322index 3851983..3fa75a9 100644
323--- a/tests/Makefile.am
324+++ b/tests/Makefile.am
325@@ -51,6 +51,7 @@ TESTS = \
326 t2310-dos-extended-2-sector-min-offset.sh \
327 t2320-dos-extended-noclobber.sh \
328 t2400-dos-hfs-partition-type.sh \
329+ t2410-dos-udf-partition-type.sh \
330 t2500-probe-corrupt-hfs.sh \
331 t3000-resize-fs.sh \
332 t3200-resize-partition.sh \
333diff --git a/tests/t2410-dos-udf-partition-type.sh b/tests/t2410-dos-udf-partition-type.sh
334new file mode 100644
335index 0000000..7cc8a02
336--- /dev/null
337+++ b/tests/t2410-dos-udf-partition-type.sh
338@@ -0,0 +1,38 @@
339+#!/bin/sh
340+# Ensure that an UDF partition in a dos table gets the right ID
341+
342+# Copyright (C) 2018 Free Software Foundation, Inc.
343+
344+# This program is free software; you can redistribute it and/or modify
345+# it under the terms of the GNU General Public License as published by
346+# the Free Software Foundation; either version 3 of the License, or
347+# (at your option) any later version.
348+
349+# This program is distributed in the hope that it will be useful,
350+# but WITHOUT ANY WARRANTY; without even the implied warranty of
351+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
352+# GNU General Public License for more details.
353+
354+# You should have received a copy of the GNU General Public License
355+# along with this program. If not, see <http://www.gnu.org/licenses/>.
356+
357+. "${srcdir=.}/init.sh"; path_prepend_ ../parted
358+
359+dev=loop-file
360+ss=$sector_size_
361+n_sectors=8000
362+
363+dd if=/dev/null of=$dev bs=$ss seek=$n_sectors || framework_failure
364+
365+# create a GPT partition table
366+parted -s $dev mklabel msdos \
367+ mkpart pri udf 2048s 4095s > out 2>&1 || fail=1
368+# expect no output
369+compare /dev/null out || fail=1
370+
371+# Extract the "type" byte of the first partition.
372+od -An -j450 -tx1 -N1 $dev > out || fail=1
373+printf ' 07\n' > exp || fail=1
374+compare exp out || fail=1
375+
376+Exit $fail
377--
3782.17.2
379
This page took 0.061239 seconds and 4 git commands to generate.