From: Ladislav Michl <ladis@linux-mips.org>
To: rauc@pengutronix.de
Cc: Trent Piepho <tpiepho@impinj.com>
Subject: [RAUC] [PATCH 2/3] Try harder to determine slot state (preview)
Date: Fri, 10 May 2019 11:49:14 +0200 [thread overview]
Message-ID: <20190510094914.GC29451@lenoch> (raw)
In-Reply-To: <20190510094803.GA29451@lenoch>
Only ubi volume by name is supported for now...
---
Makefile.am | 2 ++
include/mtd.h | 3 ++
src/config_file.c | 79 ++++++++++++++++++++++++++++++++++++++++++
src/install.c | 37 ++------------------
src/mtd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 174 insertions(+), 35 deletions(-)
create mode 100644 include/mtd.h
create mode 100644 src/mtd.c
diff --git a/Makefile.am b/Makefile.am
index 3bf4936..7e0efa4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,6 +43,7 @@ librauc_la_SOURCES = \
src/manifest.c \
src/mark.c \
src/mount.c \
+ src/mtd.c \
src/service.c \
src/signature.c \
src/utils.c \
@@ -57,6 +58,7 @@ librauc_la_SOURCES = \
include/manifest.h \
include/mark.h \
include/mount.h \
+ include/mtd.h \
include/service.h \
include/signature.h \
include/update_handler.h \
diff --git a/include/mtd.h b/include/mtd.h
new file mode 100644
index 0000000..e01a203
--- /dev/null
+++ b/include/mtd.h
@@ -0,0 +1,3 @@
+#pragma once
+
+int ubi_volume_device_id(int device, const char *volname, unsigned *major, unsigned *minor);
diff --git a/src/config_file.c b/src/config_file.c
index d966533..453d6a1 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -2,11 +2,13 @@
#include <glib.h>
#include <glib/gstdio.h>
#include <string.h>
+#include <sys/sysmacros.h>
#include "config_file.h"
#include "context.h"
#include "manifest.h"
#include "mount.h"
+#include "mtd.h"
#include "utils.h"
G_DEFINE_QUARK(r-config-error-quark, r_config_error)
@@ -501,10 +503,87 @@ typedef struct {
gchar is_device; /* vs being a loop mounted file */
} MountableObj;
+static gboolean mtd_by_name(const gchar *name, MountableObj *obj)
+{
+ return FALSE; /* TODO */
+}
+
+static gboolean mtd_by_index(guint index, MountableObj *obj)
+{
+ return FALSE; /* TODO */
+}
+
+static gboolean ubi_volume_by_name(guint index, const gchar *name, MountableObj *obj)
+{
+ unsigned major, minor;
+
+ if (ubi_volume_device_id(index, name, &major, &minor) < 0)
+ return FALSE;
+
+ obj->is_device = 1;
+ obj->dev = makedev(major, minor);
+
+ return TRUE;
+}
+
+static gboolean ubi_volume_by_index(guint index, guint vol, MountableObj *obj)
+{
+ return FALSE; /* TODO */
+}
+
/* Take a device (or file) path or name and normalize it */
static gboolean normalize_mountable_object(const gchar *name, MountableObj *obj)
{
GStatBuf st;
+ gchar *endptr;
+ guint index;
+
+ if (g_str_has_prefix(name, "mtd")) {
+ /* MTD can be also mounted as mtdX or mtd:NAME */
+ if (name[3] == ':' && name[4] != '\0') {
+ if (mtd_by_name(name, obj))
+ return TRUE;
+ } else if (g_ascii_isdigit(name[3])) {
+ index = g_ascii_strtoull(name + 3, &endptr, 0);
+ if (*endptr == '\0' && mtd_by_index(index, obj))
+ return TRUE;
+ }
+ } else if (g_str_has_prefix(name, "ubi")) {
+ /* fs/ubifs/super.c of kernel source says:
+ *
+ * The primary method of mounting UBIFS is by specifying the UBI volume
+ * character device node path. However, UBIFS may also be mounted withoug any
+ * character device node using one of the following methods:
+ *
+ * o ubiX_Y - mount UBI device number X, volume Y;
+ * o ubiY - mount UBI device number 0, volume Y;
+ * o ubiX:NAME - mount UBI device X, volume with name NAME;
+ * o ubi:NAME - mount UBI device 0, volume with name NAME.
+ *
+ * Alternative '!' separator may be used instead of ':' */
+ if ((name[3] == ':' || name[3] == '!') && name[4] != '\0') {
+ if (ubi_volume_by_name(0, name + 4, obj))
+ return TRUE;
+ } else if (g_ascii_isdigit(name[3])) {
+ index = g_ascii_strtoull(name + 3, &endptr, 0);
+ if (*endptr == '\0') {
+ if (ubi_volume_by_index(0, index, obj))
+ return TRUE;
+ } else if (*endptr == '_' && g_ascii_isdigit(endptr[1])) {
+ guint vol = g_ascii_strtoull(endptr + 1, &endptr, 0);
+ if (*endptr == '\0' && ubi_volume_by_index(index, vol, obj))
+ return TRUE;
+ } else if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0') {
+ if (ubi_volume_by_name(index, ++endptr, obj))
+ return TRUE;
+ }
+ }
+ } else if (!g_str_has_prefix(name, "/")) {
+ /* Relative paths will be from something like tmpfs, cgroups,
+ * etc. which we want to ignore rather than try to follow some
+ * random symlink named "tmpfs" in the CWD. */
+ return FALSE;
+ }
if (g_stat(name, &st) == -1) {
/* Virtual filesystems like devpts trigger case */
diff --git a/src/install.c b/src/install.c
index 2cda3be..6d8e8e9 100644
--- a/src/install.c
+++ b/src/install.c
@@ -43,30 +43,6 @@ static void install_args_update(RaucInstallArgs *args, const gchar *msg)
g_main_context_invoke(NULL, args->notify, args);
}
-static gchar *resolve_loop_device(const gchar *devicepath)
-{
- g_autofree gchar *devicename = NULL;
- g_autofree gchar *syspath = NULL;
- gchar *content = NULL;
- GError *ierror = NULL;
-
- if (!g_str_has_prefix(devicepath, "/dev/loop"))
- return g_strdup(devicepath);
-
- devicename = g_path_get_basename(devicepath);
- syspath = g_build_filename("/sys/block", devicename, "loop/backing_file", NULL);
-
- content = read_file_str(syspath, &ierror);
- if (!content) {
- g_message("%s", ierror->message);
- g_clear_error(&ierror);
- return NULL;
- }
-
- /* g_strchomp modifies the string and returns it */
- return g_strchomp(content);
-}
-
gboolean determine_slot_states(GError **error)
{
GList *slotlist = NULL;
@@ -90,17 +66,8 @@ gboolean determine_slot_states(GError **error)
mountlist = g_unix_mounts_get(NULL);
for (GList *l = mountlist; l != NULL; l = l->next) {
GUnixMountEntry *m = (GUnixMountEntry*)l->data;
- g_autofree gchar *devicepath = NULL;
- RaucSlot *s = NULL;
- /* Relative paths will be from something like tmpfs, cgroups,
- * etc. which we want to ignore rather than try to follow some
- * random symlink named "tmpfs" in the CWD. */
- if (g_unix_mount_get_device_path(m)[0] != '/')
- continue;
-
- devicepath = resolve_loop_device(g_unix_mount_get_device_path(m));
- s = find_config_slot_by_device(r_context()->config, devicepath);
- if (!s)
+ RaucSlot *s = find_config_slot_by_device(r_context()->config, g_unix_mount_get_device_path(m));
+ if (!s || s->ext_mount_point)
continue;
s->ext_mount_point = g_strdup(g_unix_mount_get_mount_path(m));
diff --git a/src/mtd.c b/src/mtd.c
new file mode 100644
index 0000000..95a8c41
--- /dev/null
+++ b/src/mtd.c
@@ -0,0 +1,88 @@
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
+#include "mtd.h"
+
+int ubi_volume_device_id(int device, const char *volname, unsigned *major, unsigned *minor)
+{
+ ssize_t len;
+ char buf[256], prefix[16], *endptr;
+ struct dirent *dp;
+ DIR *ubi_dir;
+ int prefix_len;
+ unsigned maj, min;
+ int fd, vol_fd, ubi_fd;
+
+ snprintf(buf, sizeof(buf), "/sys/class/ubi/ubi%d", device);
+ ubi_dir = opendir(buf);
+ if (!ubi_dir)
+ return -1;
+
+ ubi_fd = dirfd(ubi_dir);
+ if (ubi_fd < 0) {
+ closedir(ubi_dir);
+ return -1;
+ }
+
+ endptr = NULL;
+ prefix_len = snprintf(prefix, sizeof(prefix), "ubi%d_", device);
+
+ while ((dp = readdir(ubi_dir)) != NULL) {
+ if (dp->d_type != DT_DIR || strncmp(dp->d_name, prefix, prefix_len))
+ continue;
+
+ vol_fd = openat(ubi_fd, dp->d_name, O_CLOEXEC | O_DIRECTORY | O_PATH);
+ if (vol_fd < 0)
+ continue;
+
+ /* read volume name */
+ fd = openat(vol_fd, "name", O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ len = read(fd, buf, sizeof(buf));
+ close(fd);
+ /* Do not compare trailing newline */
+ if (--len > 0)
+ buf[len] = '\0';
+ if (len > 0 && strcmp(volname, buf) == 0) {
+ /* volume found, get device ID */
+ fd = openat(vol_fd, "dev", O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ len = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
+ /* at least colon and two digits */
+ if (len > 2) {
+ buf[len] = '\0';
+ maj = strtoul(buf, &endptr, 0);
+ if (*endptr == ':') {
+ min = strtoul(endptr + 1, &endptr, 0);
+ if (*endptr == '\0' || *endptr == '\n') {
+ close(vol_fd);
+ break;
+ }
+ }
+ endptr = NULL;
+ }
+ }
+ }
+ }
+ close(vol_fd);
+ }
+ closedir(ubi_dir);
+
+ if (endptr == NULL)
+ return -1;
+
+ *major = maj;
+ *minor = min;
+
+ return 0;
+}
+
+
--
2.20.1
_______________________________________________
RAUC mailing list
next prev parent reply other threads:[~2019-05-10 9:49 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-10 9:48 [RAUC] [RFC 0/3] Fix slots with nodev mounts Ladislav Michl
2019-05-10 9:48 ` [RAUC] [PATCH 1/3] Normalize device names to find mounted slots (2) Ladislav Michl
2019-05-10 9:49 ` Ladislav Michl [this message]
2019-05-10 9:49 ` [RAUC] [PATCH 3/3] Bind mount seed slot Ladislav Michl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190510094914.GC29451@lenoch \
--to=ladis@linux-mips.org \
--cc=rauc@pengutronix.de \
--cc=tpiepho@impinj.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox