[PATCH V2 0/2] Retrieve root device

24 views
Skip to first unread message

Stefano Babic

unread,
Mar 15, 2021, 1:57:58 PM3/15/21
to swup...@googlegroups.com, Stefano Babic
This adds a function to be used in code or in Lua to get the device
where rootfs is mounted. It tries the following algorithms:

1. Check for /proc/partition to get the device
2. Parse /proc/cmdline

In case of 2, the whole string after roo= is sent to the caller, without
any attempt to decode id (for example, UUID=.....)

Stefano Babic (2):
util: add function to retrieve root device
Lua: add getroot function

core/util.c | 83 +++++++++++++++++++++++++++++++++++++++++
corelib/lua_interface.c | 8 ++++
include/util.h | 1 +
3 files changed, 92 insertions(+)

--
2.25.1

Stefano Babic

unread,
Mar 15, 2021, 1:57:59 PM3/15/21
to swup...@googlegroups.com, Stefano Babic
get_find_root() is a utility function that returns the device mounted as
rootfs.

Signed-off-by: Stefano Babic <sba...@denx.de>
---

Changes since V1:
- parse /proc/cmdline if no suitable root device is found

core/util.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/util.h | 1 +
2 files changed, 84 insertions(+)

diff --git a/core/util.c b/core/util.c
index 2025276..dc2d106 100644
--- a/core/util.c
+++ b/core/util.c
@@ -23,6 +23,7 @@
#include <time.h>
#include <libgen.h>
#include <regex.h>
+#include <string.h>

#include "swupdate.h"
#include "util.h"
@@ -842,3 +843,85 @@ size_t snescape(char *dst, size_t n, const char *src)

return len;
}
+
+/*
+ * This returns the device name where rootfs is mounted
+ */
+static char *get_root_from_partitions(void)
+{
+ struct stat info;
+ FILE *fp;
+ char *devname = NULL;
+ unsigned long major, minor, nblocks;
+ char buf[256];
+ int ret;
+
+ if (stat("/", &info) < 0)
+ return NULL;
+
+ fp = fopen("/proc/partitions", "r");
+ if (!fp)
+ return NULL;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ ret = sscanf(buf, "%ld %ld %ld %ms",
+ &major, &minor, &nblocks, &devname);
+ if (ret != 4)
+ continue;
+ if ((major == info.st_dev / 256) && (minor == info.st_dev % 256)) {
+ fclose(fp);
+ return devname;
+ }
+ free(devname);
+ }
+
+ fclose(fp);
+ return NULL;
+}
+
+#define MAX_CMDLINE_LENGTH 4096
+static char *get_root_from_cmdline(void)
+{
+ char *buf;
+ FILE *fp;
+ char *root = NULL;
+ int ret;
+ char **parms = NULL;
+
+ fp = fopen("/proc/cmdline", "r");
+ if (!fp)
+ return NULL;
+ buf = (char *)calloc(1, MAX_CMDLINE_LENGTH + 1);
+ if (!buf) {
+ fclose(fp);
+ return NULL;
+ }
+ ret = fread(buf, 1, MAX_CMDLINE_LENGTH, fp);
+
+ if (ret > 0) {
+ parms = string_split(buf, ' ');
+ int nparms = count_string_array((const char **)parms);
+ for (unsigned int index = 0; index < nparms; index++) {
+ if (!strncmp(parms[index], "root=", strlen("root="))) {
+ const char *value = parms[index] + strlen("root=");
+ root = strdup(value);
+ break;
+ }
+ }
+ }
+ fclose(fp);
+ free_string_array(parms);
+ free(buf);
+ return root;
+}
+
+char *get_root_device(void)
+{
+ char *root = NULL;
+
+ root = get_root_from_partitions();
+ if (!root)
+ root = get_root_from_cmdline();
+
+ return root;
+}
diff --git a/include/util.h b/include/util.h
index 2987203..8447ab6 100644
--- a/include/util.h
+++ b/include/util.h
@@ -229,6 +229,7 @@ int set_aes_ivt(const char *ivt);
int get_install_info(sourcetype *source, char *buf, size_t len);
void get_install_swset(char *buf, size_t len);
void get_install_running_mode(char *buf, size_t len);
+char *get_root_device(void);

/* Setting global information */
void set_version_range(const char *minversion,
--
2.25.1

Stefano Babic

unread,
Mar 15, 2021, 1:58:02 PM3/15/21
to swup...@googlegroups.com, Stefano Babic
Signed-off-by: Stefano Babic <sba...@denx.de>
---

Chanmges since V1:
- no changes

corelib/lua_interface.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/corelib/lua_interface.c b/corelib/lua_interface.c
index f9900e4..14a50ce 100644
--- a/corelib/lua_interface.c
+++ b/corelib/lua_interface.c
@@ -808,6 +808,13 @@ l_umount_exit:
return 1;
}

+static int l_getroot(lua_State *L) {
+ char *rootdev = get_root_device();
+ lua_pushstring(L, rootdev);
+ free(rootdev);
+ return 1;
+}
+
static int l_get_bootenv(lua_State *L) {
const char *name = luaL_checkstring(L, 1);
char *value = NULL;
@@ -881,6 +888,7 @@ static const luaL_Reg l_swupdate[] = {
{ "debug", lua_notify_debug },
{ "mount", l_mount },
{ "umount", l_umount },
+ { "getroot", l_getroot },
{ NULL, NULL }
};

--
2.25.1

Christian Storm

unread,
Mar 16, 2021, 12:19:56 PM3/16/21
to swup...@googlegroups.com
Hi Stefano,

> This adds a function to be used in code or in Lua to get the device
> where rootfs is mounted. It tries the following algorithms:
>
> 1. Check for /proc/partition to get the device
> 2. Parse /proc/cmdline
>
> In case of 2, the whole string after roo= is sent to the caller, without
> any attempt to decode id (for example, UUID=.....)

Thanks!

This means I have to inspect l_getroot()'s returned string in my Lua
code to determine whether it's a valid path or a UUID or whatever.
Wouldn't it be more comfortable from the Lua realm to consume a
table { type=<enum>, value=<string> } where type's values could be,
e.g,. PATH, UUID, ....? This way, I can spare the parsing/guessing of
what that string actually in from the Lua realm... Just an idea.


Kind regards,
Christian

--
Dr. Christian Storm
Siemens AG, Technology, T RDA IOT SES-DE
Otto-Hahn-Ring 6, 81739 München, Germany

Stefano Babic

unread,
Mar 16, 2021, 1:23:11 PM3/16/21
to swup...@googlegroups.com
Hi Christian,

On 16.03.21 17:20, Christian Storm wrote:
> Hi Stefano,
>
>> This adds a function to be used in code or in Lua to get the device
>> where rootfs is mounted. It tries the following algorithms:
>>
>> 1. Check for /proc/partition to get the device
>> 2. Parse /proc/cmdline
>>
>> In case of 2, the whole string after roo= is sent to the caller, without
>> any attempt to decode id (for example, UUID=.....)
>
> Thanks!
>
> This means I have to inspect l_getroot()'s returned string in my Lua
> code to determine whether it's a valid path or a UUID or whatever.

Yes, because I don't know how the user will treat it...

> Wouldn't it be more comfortable from the Lua realm to consume a
> table { type=<enum>, value=<string> } where type's values could be,
> e.g,. PATH, UUID, ....?

Ok, so a table with two entries, and the user can access it with
table.type
table.value


> This way, I can spare the parsing/guessing of
> what that string actually in from the Lua realm... Just an idea.

Let's think about. That means we can consider Patch 1/2 ready, and Patch
2/2 should be reworked.

Regards,
Stefano


--
=====================================================================
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sba...@denx.de
=====================================================================

Christian Storm

unread,
Mar 16, 2021, 4:03:55 PM3/16/21
to swup...@googlegroups.com
Hi Stefano,

> > > This adds a function to be used in code or in Lua to get the device
> > > where rootfs is mounted. It tries the following algorithms:
> > >
> > > 1. Check for /proc/partition to get the device
> > > 2. Parse /proc/cmdline
> > >
> > > In case of 2, the whole string after roo= is sent to the caller, without
> > > any attempt to decode id (for example, UUID=.....)
> >
> > Thanks!
> >
> > This means I have to inspect l_getroot()'s returned string in my Lua
> > code to determine whether it's a valid path or a UUID or whatever.
>
> Yes, because I don't know how the user will treat it...
>
> > Wouldn't it be more comfortable from the Lua realm to consume a
> > table { type=<enum>, value=<string> } where type's values could be,
> > e.g,. PATH, UUID, ....?
>
> Ok, so a table with two entries, and the user can access it with
> table.type
> table.value

Yes, l_getroot() pushes a table and returns 1. Then, we can mimic
enum-likes in Lua as, e.g.,

swupdate.roottype = {
PLAIN = 'PLAIN',
UUID = 'UUID',
...
}

and fill the returned table's type field with the appropriate
string (or encode it otherwise following the same idea).
Then, you can conveniently use, e.g.,
if rettable.type == swupdate.roottype.PLAIN then
...
in Lua.


> > This way, I can spare the parsing/guessing of
> > what that string actually in from the Lua realm... Just an idea.
>
> Let's think about. That means we can consider Patch 1/2 ready, and Patch 2/2
> should be reworked.

If you agree to the idea, then yes to both :)

Stefano Babic

unread,
Mar 17, 2021, 5:22:04 AM3/17/21
to swup...@googlegroups.com
Ok, it is WIP..

Stefano Babic

unread,
Mar 17, 2021, 5:55:22 AM3/17/21
to swup...@googlegroups.com, Stefano Babic
This adds a function to be used in code or in Lua to get the device
where rootfs is mounted. It tries the following algorithms:

1. Check for /proc/partition to get the device
2. Parse /proc/cmdline

In case of 2, the whole string after roo= is sent to the caller, without
any attempt to decode id (for example, UUID=.....)

The function is exposed to Lua, and the caller gets a table with type
(PATH /UUID/ PARTUUIDi /PARTLABEL) and value.

Stefano Babic (2):
util: add function to retrieve root device
Lua: add getroot function

core/util.c | 83 +++++++++++++++++++++++++++++++++++++++++
corelib/lua_interface.c | 39 +++++++++++++++++++
include/lua_util.h | 7 ++++
include/util.h | 1 +
4 files changed, 130 insertions(+)

--
2.25.1

Stefano Babic

unread,
Mar 17, 2021, 5:55:23 AM3/17/21
to swup...@googlegroups.com, Stefano Babic
get_find_root() is a utility function that returns the device mounted as
rootfs.

Signed-off-by: Stefano Babic <sba...@denx.de>
---
Changes since V2:
- no changes

Stefano Babic

unread,
Mar 17, 2021, 5:55:25 AM3/17/21
to swup...@googlegroups.com, Stefano Babic
Signed-off-by: Stefano Babic <sba...@denx.de>
---
corelib/lua_interface.c | 39 +++++++++++++++++++++++++++++++++++++++
include/lua_util.h | 7 +++++++
2 files changed, 46 insertions(+)

Chanmges since V2:
- return a table with type / value

diff --git a/corelib/lua_interface.c b/corelib/lua_interface.c
index f9900e4..e4e4e9f 100644
--- a/corelib/lua_interface.c
+++ b/corelib/lua_interface.c
@@ -808,6 +808,35 @@ l_umount_exit:
return 1;
}

+static int l_getroot(lua_State *L) {
+ char *rootdev = get_root_device();
+ root_dev_type type = ROOT_DEV_PATH;
+ char **root = NULL;
+ char *value = rootdev;
+
+ root = string_split(rootdev, '=');
+ if (count_string_array((const char **)root) > 1) {
+ if (!strncmp(root[0], "UUID", strlen("UUID"))) {
+ type = ROOT_DEV_UUID;
+ } else if (strncmp(root[0], "PARTUUID", strlen("PARTUUID"))) {
+ type = ROOT_DEV_PARTUUID;
+ } else if (strncmp(root[0], "PARTLABEL", strlen("PARTLABEL"))) {
+ type = ROOT_DEV_PARTLABEL;
+ }
+ value = root[1];
+ }
+ lua_newtable (L);
+ lua_pushstring(L, "type");
+ lua_pushinteger(L, type);
+ lua_settable(L, -3);
+ lua_pushstring(L, "value");
+ lua_pushstring(L, value);
+ lua_settable(L, -3);
+ free(rootdev);
+ free_string_array(root);
+ return 1;
+}
+
static int l_get_bootenv(lua_State *L) {
const char *name = luaL_checkstring(L, 1);
char *value = NULL;
@@ -881,6 +910,7 @@ static const luaL_Reg l_swupdate[] = {
{ "debug", lua_notify_debug },
{ "mount", l_mount },
{ "umount", l_umount },
+ { "getroot", l_getroot },
{ NULL, NULL }
};

@@ -933,6 +963,15 @@ static int luaopen_swupdate(lua_State *L)
lua_push_enum(L, "PROGRESS", SUBPROCESS);
lua_settable(L, -3);

+ /* export the root device type */
+ lua_pushstring(L, "ROOT_DEVICE");
+ lua_newtable (L);
+ lua_push_enum(L, "PATH", ROOT_DEV_PATH);
+ lua_push_enum(L, "UUID", ROOT_DEV_UUID);
+ lua_push_enum(L, "PARTUUID", ROOT_DEV_PARTUUID);
+ lua_push_enum(L, "PARTLABEL", ROOT_DEV_PARTLABEL);
+ lua_settable(L, -3);
+
#ifdef CONFIG_HANDLER_IN_LUA
if (is_type(L, LUA_TYPE_HANDLER)) {
/* register handler-specific functions to swupdate module table. */
diff --git a/include/lua_util.h b/include/lua_util.h
index 1cefc88..088ad2e 100644
--- a/include/lua_util.h
+++ b/include/lua_util.h
@@ -15,6 +15,13 @@
#include "lualib.h"
#include "util.h"

+typedef enum {
+ ROOT_DEV_PATH,
+ ROOT_DEV_UUID,
+ ROOT_DEV_PARTUUID,
+ ROOT_DEV_PARTLABEL
+} root_dev_type;
+
void LUAstackDump (lua_State *L);
int run_lua_script(const char *script, const char *function, char *parms);
lua_State *lua_parser_init(const char *buf, struct dict *bootenv);
--
2.25.1

Reply all
Reply to author
Forward
0 new messages