diff options
author | Devendra Tewari <devendra.tewari@gmail.com> | 2022-08-24 07:13:04 -0300 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2022-08-24 21:42:16 +0100 |
commit | aa181897cf189263e2786d8a184918442e52ee1a (patch) | |
tree | 7bdf376c6aadc257e62bef364743fee273682035 /src/basic/devnum-util.c | |
parent | 782c6e5c9050ba2de141906732e0a7e14b0c1550 (diff) | |
download | systemd-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.c | 48 |
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; |