]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: (gpt) add API for raw partition attributes
authorMichael Marineau <michael.marineau@coreos.com>
Sat, 2 May 2015 22:52:48 +0000 (15:52 -0700)
committerKarel Zak <kzak@redhat.com>
Tue, 5 May 2015 10:39:36 +0000 (12:39 +0200)
The existing APIs can only toggle individual bits or get and set bits in
a complex text representation, making it impractical to use libfdisk for
manipulating the GPT partition attribute field in more complex ways such
as updating a value that is multiple bits wide. For example priority
based partition selection originally designed for ChromeOS includes two
integer values that are 4-bits wide.

http://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format#TOC-Trusting-the-GPT

[kzak@redhat.com: - add new symbols to .sym file and docs
                  - remove unused variables from test program]

Signed-off-by: Michael Marineau <michael.marineau@coreos.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/docs/libfdisk-sections.txt
libfdisk/src/Makemodule.am
libfdisk/src/gpt.c
libfdisk/src/libfdisk.h.in
libfdisk/src/libfdisk.sym
tests/commands.sh
tests/expected/libfdisk/gpt-all-defaults [new file with mode: 0644]
tests/expected/libfdisk/gpt-getattr [new file with mode: 0644]
tests/expected/libfdisk/gpt-setattr [new file with mode: 0644]
tests/ts/libfdisk/gpt [new file with mode: 0755]

index acee8f855af82abbfd57c44a3d2af0f15faf6a1f..02b775ea6bf26b7925dd696ccb521e038c62df77 100644 (file)
@@ -223,6 +223,8 @@ fdisk_sgi_set_bootfile
 <SECTION>
 <FILE>gpt</FILE>
 fdisk_gpt_is_hybrid
+fdisk_gpt_get_partition_attrs
+fdisk_gpt_set_partition_attrs
 GPT_FLAG_REQUIRED
 GPT_FLAG_NOBLOCK
 GPT_FLAG_LEGACYBOOT
index 347ea8e11558543ed128d36af034d4530e19a1df..00c3d9f0c08778c3530cd62c994f7ad4a2efc1cd 100644 (file)
@@ -64,6 +64,7 @@ EXTRA_DIST += \
 if BUILD_LIBFDISK_TESTS
 check_PROGRAMS += \
        test_fdisk_ask \
+       test_fdisk_gpt \
        test_fdisk_script \
        test_fdisk_utils \
        test_fdisk_version 
@@ -81,6 +82,11 @@ test_fdisk_ask_CFLAGS = $(libfdisk_tests_cflags)
 test_fdisk_ask_LDFLAGS = $(libfdisk_tests_ldflags)
 test_fdisk_ask_LDADD = $(libfdisk_tests_ldadd)
 
+test_fdisk_gpt_SOURCES = libfdisk/src/gpt.c
+test_fdisk_gpt_CFLAGS = $(libfdisk_tests_cflags)
+test_fdisk_gpt_LDFLAGS = $(libfdisk_tests_ldflags)
+test_fdisk_gpt_LDADD = $(libfdisk_tests_ldadd)
+
 test_fdisk_utils_SOURCES = libfdisk/src/utils.c
 test_fdisk_utils_CFLAGS = $(libfdisk_tests_cflags)
 test_fdisk_utils_LDFLAGS = $(libfdisk_tests_ldflags)
index 989fd752c52647f85dce59bce5aca8abead38ca6..a7ec5397a4e7e53fe2daf7e384a158d57f99de79 100644 (file)
@@ -2429,6 +2429,73 @@ int fdisk_gpt_is_hybrid(struct fdisk_context *cxt)
        return valid_pmbr(cxt) == GPT_MBR_HYBRID;
 }
 
+/**
+ * fdisk_gpt_get_partition_attrs:
+ * @cxt: context
+ * @partnum: partition number
+ * @attrs: GPT partition attributes
+ *
+ * Sets @attrs for the given partition
+ *
+ * Returns: 0 on success, <0 on error.
+ */
+int fdisk_gpt_get_partition_attrs(
+               struct fdisk_context *cxt,
+               size_t partnum,
+               uint64_t *attrs)
+{
+       struct fdisk_gpt_label *gpt;
+
+       assert(cxt);
+       assert(cxt->label);
+       assert(fdisk_is_label(cxt, GPT));
+
+       gpt = self_label(cxt);
+
+       if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
+               return -EINVAL;
+
+       *attrs = le64_to_cpu(gpt->ents[partnum].attrs);
+       return 0;
+}
+
+/**
+ * fdisk_gpt_set_partition_attrs:
+ * @cxt: context
+ * @partnum: partition number
+ * @attrs: GPT partition attributes
+ *
+ * Sets the GPT partition attributes field to @attrs.
+ *
+ * Returns: 0 on success, <0 on error.
+ */
+int fdisk_gpt_set_partition_attrs(
+               struct fdisk_context *cxt,
+               size_t partnum,
+               uint64_t attrs)
+{
+       struct fdisk_gpt_label *gpt;
+
+       assert(cxt);
+       assert(cxt->label);
+       assert(fdisk_is_label(cxt, GPT));
+
+       DBG(LABEL, ul_debug("GPT entry attributes change requested partno=%zu", partnum));
+       gpt = self_label(cxt);
+
+       if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
+               return -EINVAL;
+
+       gpt->ents[partnum].attrs = cpu_to_le64(attrs);
+       fdisk_info(cxt, _("The attributes on partition %zu changed to 0x%016" PRIx64 "."),
+                       partnum + 1, attrs);
+
+       gpt_recompute_crc(gpt->pheader, gpt->ents);
+       gpt_recompute_crc(gpt->bheader, gpt->ents);
+       fdisk_label_set_changed(cxt->label, 1);
+       return 0;
+}
+
 static int gpt_toggle_partition_flag(
                struct fdisk_context *cxt,
                size_t i,
@@ -2668,3 +2735,62 @@ struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt)
 
        return lb;
 }
+
+#ifdef TEST_PROGRAM
+int test_getattr(struct fdisk_test *ts, int argc, char *argv[])
+{
+       const char *disk = argv[1];
+       size_t part = strtoul(argv[2], NULL, 0) - 1;
+       struct fdisk_context *cxt;
+       uint64_t atters = 0;
+
+       cxt = fdisk_new_context();
+       fdisk_assign_device(cxt, disk, 1);
+
+       if (!fdisk_is_label(cxt, GPT))
+               return EXIT_FAILURE;
+
+       if (fdisk_gpt_get_partition_attrs(cxt, part, &atters))
+               return EXIT_FAILURE;
+
+       printf("%s: 0x%016" PRIx64 "\n", argv[2], atters);
+
+       fdisk_unref_context(cxt);
+       return 0;
+}
+
+int test_setattr(struct fdisk_test *ts, int argc, char *argv[])
+{
+       const char *disk = argv[1];
+       size_t part = strtoul(argv[2], NULL, 0) - 1;
+       uint64_t atters = strtoull(argv[3], NULL, 0);
+       struct fdisk_context *cxt;
+
+       cxt = fdisk_new_context();
+       fdisk_assign_device(cxt, disk, 0);
+
+       if (!fdisk_is_label(cxt, GPT))
+               return EXIT_FAILURE;
+
+       if (fdisk_gpt_set_partition_attrs(cxt, part, atters))
+               return EXIT_FAILURE;
+
+       if (fdisk_write_disklabel(cxt))
+               return EXIT_FAILURE;
+
+       fdisk_unref_context(cxt);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       struct fdisk_test tss[] = {
+               { "--getattr",  test_getattr,  "<disk> <partition>             print attributes" },
+               { "--setattr",  test_setattr,  "<disk> <partition> <value>     set attributes" },
+               { NULL }
+       };
+
+       return fdisk_run_test(tss, argc, argv);
+}
+
+#endif
index 5f75ecd14d8a3533de2f3bb41809e286e0f160af..a5a46567461de01e6aa905343a28f7141f950497 100644 (file)
@@ -531,6 +531,8 @@ extern int fdisk_sgi_create_info(struct fdisk_context *cxt);
 #define GPT_FLAG_GUIDSPECIFIC  4
 
 extern int fdisk_gpt_is_hybrid(struct fdisk_context *cxt);
+extern int fdisk_gpt_get_partition_attrs(struct fdisk_context *cxt, size_t partnum, uint64_t *attrs);
+extern int fdisk_gpt_set_partition_attrs(struct fdisk_context *cxt, size_t partnum, uint64_t attrs);
 
 
 /* script.c */
index 456a52d838e5f7a117fd546c6f9fed0a76c5156d..1e6394465d86a74d73b5871510518046dc67c97c 100644 (file)
@@ -247,4 +247,6 @@ FDISK_2.27 {
        fdisk_enable_bootbits_protection;
        fdisk_has_protected_bootbits;
        fdisk_table_get_partition_by_partno;
+       fdisk_gpt_get_partition_attrs;
+       fdisk_gpt_set_partition_attrs;
 } FDISK_2.26;
index e3ac43394d97ebc119b3e481bc34f3ac1673f920..dfb19e3151426381fb309f19b1b82bb2f6a40794 100644 (file)
@@ -7,6 +7,7 @@ TS_HELPER_CPUSET="$top_builddir/test_cpuset"
 TS_HELPER_DMESG="$top_builddir/test_dmesg"
 TS_HELPER_ISLOCAL="$top_builddir/test_islocal"
 TS_HELPER_ISMOUNTED="$top_builddir/test_ismounted"
+TS_HELPER_LIBFDISK_GPT="$top_builddir/test_fdisk_gpt"
 TS_HELPER_LIBMOUNT_CONTEXT="$top_builddir/test_mount_context"
 TS_HELPER_LIBMOUNT_LOCK="$top_builddir/test_mount_lock"
 TS_HELPER_LIBMOUNT_OPTSTR="$top_builddir/test_mount_optstr"
diff --git a/tests/expected/libfdisk/gpt-all-defaults b/tests/expected/libfdisk/gpt-all-defaults
new file mode 100644 (file)
index 0000000..8836807
--- /dev/null
@@ -0,0 +1,21 @@
+Checking that no-one is using this disk right now ... OK
+
+Disk <removed>: 10 MiB, 10485760 bytes, 20480 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
+
+>>> Script header accepted.
+>>> Script header accepted.
+>>> Created a new <removed>.
+Created a new <removed>.
+<removed>2: Created a new <removed>.
+<removed>3: 
+New situation:
+
+Device             Start   End Sectors Size Type
+<removed>1  2048 12287   10240   5M Linux filesystem
+<removed>2 12288 20446    8159   4M Linux filesystem
+
+The partition table has been altered.
+Syncing disks.
diff --git a/tests/expected/libfdisk/gpt-getattr b/tests/expected/libfdisk/gpt-getattr
new file mode 100644 (file)
index 0000000..559a9ae
--- /dev/null
@@ -0,0 +1,2 @@
+1: 0x0001000000000001
+2: 0x4030000000000000
diff --git a/tests/expected/libfdisk/gpt-setattr b/tests/expected/libfdisk/gpt-setattr
new file mode 100644 (file)
index 0000000..41af260
--- /dev/null
@@ -0,0 +1,2 @@
+GUID:56,57,58,59,60,61,62,63
+LegacyBIOSBootable
diff --git a/tests/ts/libfdisk/gpt b/tests/ts/libfdisk/gpt
new file mode 100755 (executable)
index 0000000..2de6b1a
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/bash
+#
+# 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="GPT"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+TESTPROG="$TS_HELPER_LIBFDISK_GPT"
+ts_check_test_command "$TESTPROG"
+ts_check_test_command "$TS_CMD_SFDISK"
+
+TEST_IMAGE_NAME=$(ts_image_init 10)
+
+ts_init_subtest "all-defaults"
+$TS_CMD_SFDISK --unit S ${TEST_IMAGE_NAME} >> $TS_OUTPUT 2>&1 <<EOF
+label: gpt
+label-id: b181c399-4711-4c52-8b65-9e764541218d
+
+size=5M, attrs="RequiredPartiton,48"
+attrs="52,53,62"
+EOF
+ts_fdisk_clean ${TEST_IMAGE_NAME}
+ts_finalize_subtest
+
+ts_init_subtest "getattr"
+ts_valgrind $TESTPROG --getattr ${TEST_IMAGE_NAME} 1 >> $TS_OUTPUT 2>&1
+ts_valgrind $TESTPROG --getattr ${TEST_IMAGE_NAME} 2 >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "setattr"
+ts_valgrind $TESTPROG --setattr ${TEST_IMAGE_NAME} 1 0xff00000000000000 >> $TS_OUTPUT 2>&1
+ts_valgrind $TESTPROG --setattr ${TEST_IMAGE_NAME} 2 0x4 >> $TS_OUTPUT 2>&1
+$TS_CMD_SFDISK --part-attrs ${TEST_IMAGE_NAME} 1 >> $TS_OUTPUT 2>&1
+$TS_CMD_SFDISK --part-attrs ${TEST_IMAGE_NAME} 2 >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_finalize