All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libfdisk: (gpt) add API for raw partition attributes
@ 2015-05-02 22:52 Michael Marineau
  2015-05-05 10:50 ` Karel Zak
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Marineau @ 2015-05-02 22:52 UTC (permalink / raw)
  To: util-linux; +Cc: Michael Marineau

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

Signed-off-by: Michael Marineau <michael.marineau@coreos.com>
---
 libfdisk/src/Makemodule.am               |   6 ++
 libfdisk/src/gpt.c                       | 128 +++++++++++++++++++++++++++++++
 libfdisk/src/libfdisk.h.in               |   2 +
 tests/commands.sh                        |   1 +
 tests/expected/libfdisk/gpt-all-defaults |  21 +++++
 tests/expected/libfdisk/gpt-getattr      |   2 +
 tests/expected/libfdisk/gpt-setattr      |   2 +
 tests/ts/libfdisk/gpt                    |  52 +++++++++++++
 8 files changed, 214 insertions(+)
 create mode 100644 tests/expected/libfdisk/gpt-all-defaults
 create mode 100644 tests/expected/libfdisk/gpt-getattr
 create mode 100644 tests/expected/libfdisk/gpt-setattr
 create mode 100755 tests/ts/libfdisk/gpt

diff --git a/libfdisk/src/Makemodule.am b/libfdisk/src/Makemodule.am
index 347ea8e..00c3d9f 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 989fd75..e901a4a 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,64 @@ 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;
+	struct fdisk_label *lb;
+	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;
+	struct fdisk_label *lb;
+
+	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 5f75ecd..a5a4656 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/tests/commands.sh b/tests/commands.sh
index e3ac433..dfb19e3 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 0000000..8836807
--- /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 0000000..559a9ae
--- /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 0000000..41af260
--- /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 0000000..2de6b1a
--- /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
-- 
2.0.5


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] libfdisk: (gpt) add API for raw partition attributes
  2015-05-02 22:52 [PATCH] libfdisk: (gpt) add API for raw partition attributes Michael Marineau
@ 2015-05-05 10:50 ` Karel Zak
  0 siblings, 0 replies; 2+ messages in thread
From: Karel Zak @ 2015-05-05 10:50 UTC (permalink / raw)
  To: Michael Marineau; +Cc: util-linux

On Sat, May 02, 2015 at 03:52:48PM -0700, Michael Marineau wrote:
> 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.

 Hmm... my goal is to minimize number of label specific functions, but
 GPT attributes is so specific that it makes sense to export it by API.

 Applied, thanks (and extra thanks for the test!).

    Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-05-05 10:50 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-02 22:52 [PATCH] libfdisk: (gpt) add API for raw partition attributes Michael Marineau
2015-05-05 10:50 ` Karel Zak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.