summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Marineau2015-05-03 00:52:48 +0200
committerKarel Zak2015-05-05 12:39:36 +0200
commit4a4a0927c6b761f7b8b29b00491b22b3553720e8 (patch)
tree91dc14b26e6650b10dbb94af2535354724b3736c
parentlibfdisk: (gpt) fix check for beginning of protective partition (diff)
downloadkernel-qcow2-util-linux-4a4a0927c6b761f7b8b29b00491b22b3553720e8.tar.gz
kernel-qcow2-util-linux-4a4a0927c6b761f7b8b29b00491b22b3553720e8.tar.xz
kernel-qcow2-util-linux-4a4a0927c6b761f7b8b29b00491b22b3553720e8.zip
libfdisk: (gpt) add API for raw partition attributes
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>
-rw-r--r--libfdisk/docs/libfdisk-sections.txt2
-rw-r--r--libfdisk/src/Makemodule.am6
-rw-r--r--libfdisk/src/gpt.c126
-rw-r--r--libfdisk/src/libfdisk.h.in2
-rw-r--r--libfdisk/src/libfdisk.sym2
-rw-r--r--tests/commands.sh1
-rw-r--r--tests/expected/libfdisk/gpt-all-defaults21
-rw-r--r--tests/expected/libfdisk/gpt-getattr2
-rw-r--r--tests/expected/libfdisk/gpt-setattr2
-rwxr-xr-xtests/ts/libfdisk/gpt52
10 files changed, 216 insertions, 0 deletions
diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt
index acee8f855..02b775ea6 100644
--- a/libfdisk/docs/libfdisk-sections.txt
+++ b/libfdisk/docs/libfdisk-sections.txt
@@ -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
diff --git a/libfdisk/src/Makemodule.am b/libfdisk/src/Makemodule.am
index 347ea8e11..00c3d9f0c 100644
--- a/libfdisk/src/Makemodule.am
+++ b/libfdisk/src/Makemodule.am
@@ -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)
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 989fd752c..a7ec5397a 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -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
diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in
index 5f75ecd14..a5a465674 100644
--- a/libfdisk/src/libfdisk.h.in
+++ b/libfdisk/src/libfdisk.h.in
@@ -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 */
diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym
index 456a52d83..1e6394465 100644
--- a/libfdisk/src/libfdisk.sym
+++ b/libfdisk/src/libfdisk.sym
@@ -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;
diff --git a/tests/commands.sh b/tests/commands.sh
index e3ac43394..dfb19e315 100644
--- a/tests/commands.sh
+++ b/tests/commands.sh
@@ -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
index 000000000..883680744
--- /dev/null
+++ b/tests/expected/libfdisk/gpt-all-defaults
@@ -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
index 000000000..559a9ae72
--- /dev/null
+++ b/tests/expected/libfdisk/gpt-getattr
@@ -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
index 000000000..41af260f4
--- /dev/null
+++ b/tests/expected/libfdisk/gpt-setattr
@@ -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
index 000000000..2de6b1a57
--- /dev/null
+++ b/tests/ts/libfdisk/gpt
@@ -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