diff mbox series

[v3,1/2] handlers: add diskformat handler

Message ID 20210806123318.32591-2-roland.gaudig-oss@weidmueller.com
State Accepted
Headers show
Series handlers: diskformat: Add separate diskformat handler | expand

Commit Message

Roland Gaudig Aug. 6, 2021, 12:33 p.m. UTC
From: Roland Gaudig <roland.gaudig@weidmueller.com>

Currently the discpart handler only creates a new file system when the
partition table has changed.

In cases where there exists an unused and unformatted spare partion which
shall be activated by a later update, it is necessary to format such a
partition even if the partition table has not been altered.

Also there are cases when creating a file system on a single partition is
desired, but there is no partitioning scheme specified inside the
sw-description.

Therefore, this commit introduces a new diskformat handler which allows
creating a file system independently from the partitioning process.
Before creating a new file system it checks whether the desired file system
already exists and only writes if not.

In case it is desired to create a new file system anyway, this can be
achieved by setting the property "force" to "true".

	partitions: (
	{
		type = "diskformat";
		device = "/dev/mmcblk0p1";

		properties: {
			fstype = "vfat";
			force = "true";
		}
	})

The diskformat handler will be active when the configuration option
CONFIG_DISKFORMAT_HANDLER is selected.

Signed-off-by: Roland Gaudig <roland.gaudig@weidmueller.com>
---

(no changes since v1)

 Makefile.flags                 |  4 ++
 configs/all_handlers_defconfig |  1 +
 fs/Makefile                    |  1 +
 fs/diskformat.c                | 67 +++++++++++++++++++++++
 handlers/Config.in             | 18 ++++---
 handlers/Makefile              |  1 +
 handlers/diskformat_handler.c  | 99 ++++++++++++++++++++++++++++++++++
 handlers/diskpart_handler.c    | 42 ++-------------
 include/fs_interface.h         |  2 +
 9 files changed, 189 insertions(+), 46 deletions(-)
 create mode 100644 fs/diskformat.c
 create mode 100644 handlers/diskformat_handler.c
diff mbox series

Patch

diff --git a/Makefile.flags b/Makefile.flags
index d3ca49d..e549b46 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -185,6 +185,10 @@  ifeq ($(CONFIG_DISKPART),y)
 LDLIBS += fdisk
 endif
 
+ifeq ($(CONFIG_DISKFORMAT_HANDLER),y)
+LDLIBS += blkid
+endif
+
 ifeq ($(CONFIG_EXT_FILESYSTEM),y)
 LDLIBS += ext2fs uuid blkid
 endif
diff --git a/configs/all_handlers_defconfig b/configs/all_handlers_defconfig
index c7f2dd1..384238a 100644
--- a/configs/all_handlers_defconfig
+++ b/configs/all_handlers_defconfig
@@ -15,6 +15,7 @@  CONFIG_UBIVOL=y
 CONFIG_CFI=y
 CONFIG_DISKPART=y
 CONFIG_DISKFORMAT=y
+CONFIG_DISKFORMAT_HANDLER=y
 CONFIG_FAT_FILESYSTEM=y
 CONFIG_EXT_FILESYSTEM=y
 CONFIG_RAW=y
diff --git a/fs/Makefile b/fs/Makefile
index 7fe70ae..0ffe4e1 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -2,6 +2,7 @@ 
 #
 # SPDX-License-Identifier: GPL-2.0-only
 
+lib-$(CONFIG_DISKFORMAT) += diskformat.o
 lib-$(CONFIG_FAT_FILESYSTEM) += diskio.o \
 				fat_fs.o \
 				ff.o
diff --git a/fs/diskformat.c b/fs/diskformat.c
new file mode 100644
index 0000000..450dd17
--- /dev/null
+++ b/fs/diskformat.c
@@ -0,0 +1,67 @@ 
+/*
+ * Copyright (C) 2021 Weidmueller Interface GmbH & Co. KG
+ * Roland Gaudig <roland.gaudig@weidmueller.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0-only
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <util.h>
+#include <handler.h>
+#include <blkid/blkid.h>
+#include <fs_interface.h>
+
+#if defined(CONFIG_EXT_FILESYSTEM)
+static inline int ext_mkfs_short(const char *device_name, const char *fstype)
+{
+	return ext_mkfs(device_name, fstype, 0, NULL);
+}
+#endif
+
+struct supported_filesystems {
+	const char *fstype;
+	int (*mkfs)(const char *device_name, const char *fstype);
+};
+
+static struct supported_filesystems fs[] = {
+#if defined(CONFIG_FAT_FILESYSTEM)
+	{"vfat", fat_mkfs},
+#endif
+#if defined(CONFIG_EXT_FILESYSTEM)
+	{"ext2", ext_mkfs_short},
+	{"ext3", ext_mkfs_short},
+	{"ext4", ext_mkfs_short},
+#endif
+};
+
+int diskformat_mkfs(char *device, char *fstype)
+{
+	int index;
+	int ret = 0;
+
+	if (!device || !fstype) {
+		ERROR("Uninitialized pointer as device/fstype argument");
+		return -EINVAL;
+	}
+
+	for (index = 0; index < ARRAY_SIZE(fs); index++) {
+		if (!strcmp(fs[index].fstype, fstype))
+			break;
+	}
+	if (index >= ARRAY_SIZE(fs)) {
+		ERROR("%s file system type not supported.", fstype);
+		return -EINVAL;
+	}
+
+	TRACE("Creating %s file system on %s", fstype, device);
+	ret = fs[index].mkfs(device, fstype);
+
+	if (ret) {
+		ERROR("creating %s file system on %s failed. %d",
+		      fstype, device, ret);
+		return -EFAULT;
+	}
+
+	return ret;
+}
diff --git a/handlers/Config.in b/handlers/Config.in
index a0cc5a3..36f3ca4 100644
--- a/handlers/Config.in
+++ b/handlers/Config.in
@@ -106,15 +106,19 @@  config DISKPART
 comment "diskpart support needs libfdisk"
 	depends on !HAVE_LIBFDISK
 
-if DISKPART
-
-menuconfig DISKFORMAT
-        bool "diskpart extension for creating file systems"
+config DISKFORMAT
+	bool "diskpart extension for creating file systems"
 	depends on DISKPART
+	help
+	  This extension allows formatting newly created partitions.
+
+config DISKFORMAT_HANDLER
+	bool "diskformat handler for creating file systems"
+	select DISKFORMAT
 	default n
 	help
-	  This extension of the diskpart handler allows creating filesystems
-	  on empty partitions.
+	  The diskformat handler allows creating filesystems on empty
+	  partitions.
 
 if DISKFORMAT
 
@@ -122,8 +126,6 @@  source fs/Config.in
 
 endif
 
-endif
-
 config UNIQUEUUID
 	bool "uniqueuuid"
 	depends on HAVE_LIBBLKID
diff --git a/handlers/Makefile b/handlers/Makefile
index 1f61f60..534259c 100644
--- a/handlers/Makefile
+++ b/handlers/Makefile
@@ -11,6 +11,7 @@  obj-y	+= dummy_handler.o
 obj-$(CONFIG_ARCHIVE) += archive_handler.o
 obj-$(CONFIG_BOOTLOADERHANDLER) += boot_handler.o
 obj-$(CONFIG_CFI)	+= flash_handler.o
+obj-$(CONFIG_DISKFORMAT_HANDLER)	+= diskformat_handler.o
 obj-$(CONFIG_DISKPART)	+= diskpart_handler.o
 obj-$(CONFIG_UNIQUEUUID)	+= uniqueuuid_handler.o
 obj-$(CONFIG_CFIHAMMING1)+= flash_hamming1_handler.o
diff --git a/handlers/diskformat_handler.c b/handlers/diskformat_handler.c
new file mode 100644
index 0000000..409a35e
--- /dev/null
+++ b/handlers/diskformat_handler.c
@@ -0,0 +1,99 @@ 
+/*
+ * Copyright (C) 2021 Weidmueller Interface GmbH & Co. KG
+ * Roland Gaudig <roland.gaudig@weidmueller.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0-only
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <util.h>
+#include <handler.h>
+#include <blkid/blkid.h>
+#include <fs_interface.h>
+
+void diskformat_handler(void);
+
+/*
+ * Checks if file system fstype already exists on device.
+ * return 0 if not exists, 1 if exists, negative values on failure
+ */
+static int fs_exists(char *device, char *fstype)
+{
+	char buf[10];
+	const char *value = buf;
+	size_t len;
+	blkid_probe pr;
+	int ret = 0;
+
+	pr = blkid_new_probe_from_filename(device);
+
+	if (!pr) {
+		ERROR("%s: failed to create libblkid probe",
+		      device);
+		return -EFAULT;
+	}
+
+	while (blkid_do_probe(pr) == 0) {
+		if (blkid_probe_lookup_value(pr, "TYPE", &value, &len)) {
+			ERROR("blkid_probe_lookup_value failed");
+			ret = -EFAULT;
+			break;
+		}
+
+		if (!strncmp(value, fstype, sizeof(buf))) {
+			ret = 1;
+			break;
+		}
+	}
+	blkid_free_probe(pr);
+
+	return ret;
+}
+
+static int diskformat(struct img_type *img,
+		      void __attribute__ ((__unused__)) *data)
+{
+	int ret = 0;
+
+	if (!strlen(img->device)) {
+		ERROR("diskpart handler requires setting \"device\" attribute");
+		return -EINVAL;
+	}
+
+	char *fstype = dict_get_value(&img->properties, "fstype");
+
+	if (!fstype) {
+		ERROR("diskpart handler requires setting \"fstype\" attribute");
+		return -EINVAL;
+	}
+
+	char *force = dict_get_value(&img->properties, "force");
+
+	if (force != NULL && strcmp(force, "true") == 0) {
+		; /* Skip file system exists check */
+	} else {
+		/* Check if file system exists */
+		ret = fs_exists(img->device, fstype);
+
+		if (ret < 0)
+			return ret;
+
+		if (ret) {
+			TRACE("Found %s file system on %s, skip mkfs",
+			      fstype, img->device);
+			return 0;
+		}
+	}
+
+	/* File system does not exist, create new file system */
+	ret = diskformat_mkfs(img->device, fstype);
+	return ret;
+}
+
+__attribute__((constructor))
+void diskformat_handler(void)
+{
+	register_handler("diskformat", diskformat,
+			 PARTITION_HANDLER | NO_DATA_HANDLER, NULL);
+}
diff --git a/handlers/diskpart_handler.c b/handlers/diskpart_handler.c
index b5c9a42..a0a47d0 100644
--- a/handlers/diskpart_handler.c
+++ b/handlers/diskpart_handler.c
@@ -16,10 +16,10 @@ 
 #include <sys/file.h>
 #include <sys/types.h>
 #include <libfdisk/libfdisk.h>
+#include <fs_interface.h>
 #include "swupdate.h"
 #include "handler.h"
 #include "util.h"
-#include "fs_interface.h"
 
 void diskpart_handler(void);
 
@@ -31,12 +31,6 @@  void diskpart_handler(void);
 /* Linux native partition type */
  #define GPT_DEFAULT_ENTRY_TYPE "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
 
-#if defined (CONFIG_EXT_FILESYSTEM)
-static inline int ext_mkfs_short(const char *device_name, const char *fstype) {
-	return ext_mkfs(device_name,fstype, 0, NULL);
-}
-#endif
-
 /*
  * We will only have a parent in hybrid mode.
  */
@@ -47,22 +41,6 @@  static inline int ext_mkfs_short(const char *device_name, const char *fstype) {
  */
 #define PARENT(cxt) fdisk_get_parent(cxt) ? fdisk_get_parent(cxt) : cxt
 
-struct supported_filesystems {
-	const char *fstype;
-	int	(*mkfs) (const char *device_name, const char *fstype);
-};
-
-static struct supported_filesystems fs[] = {
-#if defined(CONFIG_FAT_FILESYSTEM)
-	{"vfat", fat_mkfs},
-#endif
-#if defined (CONFIG_EXT_FILESYSTEM)
-	{"ext2", ext_mkfs_short},
-	{"ext3", ext_mkfs_short},
-	{"ext4", ext_mkfs_short},
-#endif
-};
-
 /**
  * Keys for the properties field in sw-description
  */
@@ -942,7 +920,6 @@  handler_release:
 	/* Create filesystems */
 	if (!ret && createtable->parent) {
 		LIST_FOREACH(part, &priv.listparts, next) {
-			int index;
 			/*
 			 * priv.listparts counts partitions starting with 0,
 			 * but fdisk_partname expects the first partition having
@@ -952,25 +929,14 @@  handler_release:
 
 			if (!strlen(part->fstype))
 				continue;  /* Don't touch partitions without fstype */
-			for (index = 0; index < ARRAY_SIZE(fs); index++) {
-				if (!strcmp(fs[index].fstype, part->fstype))
-					break;
-			}
-			if (index >= ARRAY_SIZE(fs)) {
-				ERROR("partition-%lu %s filesystem type not supported.", partno, part->fstype);
-				ret = -EINVAL;
-				break;
-			}
 
 			char *device = NULL;
+
 			device = fdisk_partname(img->device, partno);
-			TRACE("Creating %s file system on partition-%lu, device %s", part->fstype, partno, device);
-			ret = fs[index].mkfs(device, part->fstype);
+			ret = diskformat_mkfs(device, part->fstype);
 			free(device);
-			if (ret) {
-				ERROR("creating %s file system failed. %d", part->fstype, ret);
+			if (ret)
 				break;
-			}
 		}
 	}
 #endif
diff --git a/include/fs_interface.h b/include/fs_interface.h
index e871257..c0120e9 100644
--- a/include/fs_interface.h
+++ b/include/fs_interface.h
@@ -7,6 +7,8 @@ 
 #ifndef _FS_INTERFACE_H
 #define _FS_INTERFACE_H
 
+int diskformat_mkfs(char *device, char *fstype);
+
 #if defined(CONFIG_FAT_FILESYSTEM)
 extern int fat_mkfs(const char *device_name, const char *fstype);
 #endif