summaryrefslogtreecommitdiff
path: root/src/basic/devnum-util.c
diff options
context:
space:
mode:
authorDevendra Tewari <devendra.tewari@gmail.com>2022-08-24 07:13:04 -0300
committerLuca Boccassi <luca.boccassi@gmail.com>2022-08-24 21:42:16 +0100
commitaa181897cf189263e2786d8a184918442e52ee1a (patch)
tree7bdf376c6aadc257e62bef364743fee273682035 /src/basic/devnum-util.c
parent782c6e5c9050ba2de141906732e0a7e14b0c1550 (diff)
downloadsystemd-aa181897cf189263e2786d8a184918442e52ee1a.tar.gz
systemd-growfs: remove dependency on udev symlinks
systemd-growfs currently requires that udev ran first to work (because /dev/block/ symlinks must exist) but that is not what happens when we're not using initrd and systemd is PID1.
Diffstat (limited to 'src/basic/devnum-util.c')
-rw-r--r--src/basic/devnum-util.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/basic/devnum-util.c b/src/basic/devnum-util.c
index 70c07315c5..fbefa2bd69 100644
--- a/src/basic/devnum-util.c
+++ b/src/basic/devnum-util.c
@@ -5,6 +5,7 @@
#include "chase-symlinks.h"
#include "devnum-util.h"
+#include "fs-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
@@ -57,6 +58,53 @@ int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret) {
return 0;
}
+int device_path_make_major_minor_sysfs(mode_t mode, dev_t devnum, char **ret) {
+ _cleanup_free_ char *syspath = NULL, *link = NULL, *fname = NULL;
+ _cleanup_free_ char *devpath = NULL;
+ const char *t;
+ int r;
+
+ /* Generates the /dev/... path given a dev_t. What makes this different
+ * from device_path_make_major_minor is that it works even when udev
+ * hasn't yet run */
+
+ if (S_ISCHR(mode))
+ t = "char";
+ else if (S_ISBLK(mode))
+ t = "block";
+ else
+ return -ENODEV;
+
+ if (asprintf(&syspath, "/sys/dev/%s/" DEVNUM_FORMAT_STR, t, DEVNUM_FORMAT_VAL(devnum)) < 0)
+ return -ENOMEM;
+
+ r = readlink_malloc(syspath, &link);
+ if (r < 0)
+ return r;
+
+ r = path_extract_filename(link, &fname);
+ if (r < 0)
+ return r;
+
+ devpath = path_join("/dev", fname);
+ if (!devpath)
+ return -ENOMEM;
+
+ struct stat st;
+ if (stat(devpath, &st) < 0)
+ return -errno;
+
+ if (((st.st_mode ^ mode) & S_IFMT) != 0)
+ return S_ISBLK(mode) ? -ENOTBLK : -ENODEV;
+
+ if (st.st_rdev != devnum)
+ return -ENXIO;
+
+ *ret = TAKE_PTR(devpath);
+
+ return 0;
+}
+
int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret) {
_cleanup_free_ char *p = NULL;
int r;