]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/devnum-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "chase-symlinks.h"
7 #include "devnum-util.h"
8 #include "parse-util.h"
10 #include "string-util.h"
12 int parse_devnum(const char *s
, dev_t
*ret
) {
18 n
= strspn(s
, DIGITS
);
21 if (n
> DECIMAL_STR_MAX(dev_t
))
26 major
= strndupa_safe(s
, n
);
27 r
= safe_atou(major
, &x
);
31 r
= safe_atou(s
+ n
+ 1, &y
);
35 if (!DEVICE_MAJOR_VALID(x
) || !DEVICE_MINOR_VALID(y
))
42 int device_path_make_major_minor(mode_t mode
, dev_t devnum
, char **ret
) {
45 /* Generates the /dev/{char|block}/MAJOR:MINOR path for a dev_t */
49 else if (S_ISBLK(mode
))
54 if (asprintf(ret
, "/dev/%s/" DEVNUM_FORMAT_STR
, t
, DEVNUM_FORMAT_VAL(devnum
)) < 0)
60 int device_path_make_canonical(mode_t mode
, dev_t devnum
, char **ret
) {
61 _cleanup_free_
char *p
= NULL
;
64 /* Finds the canonical path for a device, i.e. resolves the /dev/{char|block}/MAJOR:MINOR path to the end. */
68 if (major(devnum
) == 0 && minor(devnum
) == 0) {
71 /* A special hack to make sure our 'inaccessible' device nodes work. They won't have symlinks in
72 * /dev/block/ and /dev/char/, hence we handle them specially here. */
75 s
= strdup("/run/systemd/inaccessible/chr");
76 else if (S_ISBLK(mode
))
77 s
= strdup("/run/systemd/inaccessible/blk");
88 r
= device_path_make_major_minor(mode
, devnum
, &p
);
92 return chase_symlinks(p
, NULL
, 0, ret
, NULL
);
95 int device_path_parse_major_minor(const char *path
, mode_t
*ret_mode
, dev_t
*ret_devnum
) {
100 /* Tries to extract the major/minor directly from the device path if we can. Handles /dev/block/ and /dev/char/
101 * paths, as well out synthetic inaccessible device nodes. Never goes to disk. Returns -ENODEV if the device
102 * path cannot be parsed like this. */
104 if (path_equal(path
, "/run/systemd/inaccessible/chr")) {
106 devnum
= makedev(0, 0);
107 } else if (path_equal(path
, "/run/systemd/inaccessible/blk")) {
109 devnum
= makedev(0, 0);
113 w
= path_startswith(path
, "/dev/block/");
117 w
= path_startswith(path
, "/dev/char/");
124 r
= parse_devnum(w
, &devnum
);
132 *ret_devnum
= devnum
;