--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <string.h>
+#include <sys/stat.h>
+
+#include "chase-symlinks.h"
+#include "devnum-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "string-util.h"
+
+int parse_devnum(const char *s, dev_t *ret) {
+ const char *major;
+ unsigned x, y;
+ size_t n;
+ int r;
+
+ n = strspn(s, DIGITS);
+ if (n == 0)
+ return -EINVAL;
+ if (s[n] != ':')
+ return -EINVAL;
+
+ major = strndupa_safe(s, n);
+ r = safe_atou(major, &x);
+ if (r < 0)
+ return r;
+
+ r = safe_atou(s + n + 1, &y);
+ if (r < 0)
+ return r;
+
+ if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y))
+ return -ERANGE;
+
+ *ret = makedev(x, y);
+ return 0;
+}
+
+int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret) {
+ const char *t;
+
+ /* Generates the /dev/{char|block}/MAJOR:MINOR path for a dev_t */
+
+ if (S_ISCHR(mode))
+ t = "char";
+ else if (S_ISBLK(mode))
+ t = "block";
+ else
+ return -ENODEV;
+
+ if (asprintf(ret, "/dev/%s/%u:%u", t, major(devnum), minor(devnum)) < 0)
+ return -ENOMEM;
+
+ return 0;
+}
+
+int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret) {
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ /* Finds the canonical path for a device, i.e. resolves the /dev/{char|block}/MAJOR:MINOR path to the end. */
+
+ assert(ret);
+
+ if (major(devnum) == 0 && minor(devnum) == 0) {
+ char *s;
+
+ /* A special hack to make sure our 'inaccessible' device nodes work. They won't have symlinks in
+ * /dev/block/ and /dev/char/, hence we handle them specially here. */
+
+ if (S_ISCHR(mode))
+ s = strdup("/run/systemd/inaccessible/chr");
+ else if (S_ISBLK(mode))
+ s = strdup("/run/systemd/inaccessible/blk");
+ else
+ return -ENODEV;
+
+ if (!s)
+ return -ENOMEM;
+
+ *ret = s;
+ return 0;
+ }
+
+ r = device_path_make_major_minor(mode, devnum, &p);
+ if (r < 0)
+ return r;
+
+ return chase_symlinks(p, NULL, 0, ret, NULL);
+}
+
+int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devnum) {
+ mode_t mode;
+ dev_t devnum;
+ int r;
+
+ /* Tries to extract the major/minor directly from the device path if we can. Handles /dev/block/ and /dev/char/
+ * paths, as well out synthetic inaccessible device nodes. Never goes to disk. Returns -ENODEV if the device
+ * path cannot be parsed like this. */
+
+ if (path_equal(path, "/run/systemd/inaccessible/chr")) {
+ mode = S_IFCHR;
+ devnum = makedev(0, 0);
+ } else if (path_equal(path, "/run/systemd/inaccessible/blk")) {
+ mode = S_IFBLK;
+ devnum = makedev(0, 0);
+ } else {
+ const char *w;
+
+ w = path_startswith(path, "/dev/block/");
+ if (w)
+ mode = S_IFBLK;
+ else {
+ w = path_startswith(path, "/dev/char/");
+ if (!w)
+ return -ENODEV;
+
+ mode = S_IFCHR;
+ }
+
+ r = parse_devnum(w, &devnum);
+ if (r < 0)
+ return r;
+ }
+
+ if (ret_mode)
+ *ret_mode = mode;
+ if (ret_devnum)
+ *ret_devnum = devnum;
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+int parse_devnum(const char *s, dev_t *ret);
+
+/* glibc and the Linux kernel have different ideas about the major/minor size. These calls will check whether the
+ * specified major is valid by the Linux kernel's standards, not by glibc's. Linux has 20bits of minor, and 12 bits of
+ * major space. See MINORBITS in linux/kdev_t.h in the kernel sources. (If you wonder why we define _y here, instead of
+ * comparing directly >= 0: it's to trick out -Wtype-limits, which would otherwise complain if the type is unsigned, as
+ * such a test would be pointless in such a case.) */
+
+#define DEVICE_MAJOR_VALID(x) \
+ ({ \
+ typeof(x) _x = (x), _y = 0; \
+ _x >= _y && _x < (UINT32_C(1) << 12); \
+ \
+ })
+
+#define DEVICE_MINOR_VALID(x) \
+ ({ \
+ typeof(x) _x = (x), _y = 0; \
+ _x >= _y && _x < (UINT32_C(1) << 20); \
+ })
+
+int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret);
+int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret);
+int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devnum);
+
+static inline bool devnum_set_and_equal(dev_t a, dev_t b) {
+ /* Returns true if a and b definitely refer to the same device. If either is zero, this means "don't
+ * know" and we'll return false */
+ return a == b && a != 0;
+}
'conf-files.c',
'conf-files.h',
'def.h',
+ 'devnum-util.c',
+ 'devnum-util.h',
'dirent-util.c',
'dirent-util.h',
'dns-def.h',
return 0;
}
-int parse_dev(const char *s, dev_t *ret) {
- const char *major;
- unsigned x, y;
- size_t n;
- int r;
-
- n = strspn(s, DIGITS);
- if (n == 0)
- return -EINVAL;
- if (s[n] != ':')
- return -EINVAL;
-
- major = strndupa_safe(s, n);
- r = safe_atou(major, &x);
- if (r < 0)
- return r;
-
- r = safe_atou(s + n + 1, &y);
- if (r < 0)
- return r;
-
- if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y))
- return -ERANGE;
-
- *ret = makedev(x, y);
- return 0;
-}
-
int parse_oom_score_adjust(const char *s, int *ret) {
int r, v;
typedef unsigned long loadavg_t;
int parse_boolean(const char *v) _pure_;
-int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s);
return stat_verify_directory(&st);
}
-int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret) {
- const char *t;
-
- /* Generates the /dev/{char|block}/MAJOR:MINOR path for a dev_t */
-
- if (S_ISCHR(mode))
- t = "char";
- else if (S_ISBLK(mode))
- t = "block";
- else
- return -ENODEV;
-
- if (asprintf(ret, "/dev/%s/%u:%u", t, major(devno), minor(devno)) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- /* Finds the canonical path for a device, i.e. resolves the /dev/{char|block}/MAJOR:MINOR path to the end. */
-
- assert(ret);
-
- if (major(devno) == 0 && minor(devno) == 0) {
- char *s;
-
- /* A special hack to make sure our 'inaccessible' device nodes work. They won't have symlinks in
- * /dev/block/ and /dev/char/, hence we handle them specially here. */
-
- if (S_ISCHR(mode))
- s = strdup("/run/systemd/inaccessible/chr");
- else if (S_ISBLK(mode))
- s = strdup("/run/systemd/inaccessible/blk");
- else
- return -ENODEV;
-
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
- }
-
- r = device_path_make_major_minor(mode, devno, &p);
- if (r < 0)
- return r;
-
- return chase_symlinks(p, NULL, 0, ret, NULL);
-}
-
-int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) {
- mode_t mode;
- dev_t devno;
- int r;
-
- /* Tries to extract the major/minor directly from the device path if we can. Handles /dev/block/ and /dev/char/
- * paths, as well out synthetic inaccessible device nodes. Never goes to disk. Returns -ENODEV if the device
- * path cannot be parsed like this. */
-
- if (path_equal(path, "/run/systemd/inaccessible/chr")) {
- mode = S_IFCHR;
- devno = makedev(0, 0);
- } else if (path_equal(path, "/run/systemd/inaccessible/blk")) {
- mode = S_IFBLK;
- devno = makedev(0, 0);
- } else {
- const char *w;
-
- w = path_startswith(path, "/dev/block/");
- if (w)
- mode = S_IFBLK;
- else {
- w = path_startswith(path, "/dev/char/");
- if (!w)
- return -ENODEV;
-
- mode = S_IFCHR;
- }
-
- r = parse_dev(w, &devno);
- if (r < 0)
- return r;
- }
-
- if (ret_mode)
- *ret_mode = mode;
- if (ret_devno)
- *ret_devno = devno;
-
- return 0;
-}
-
int proc_mounted(void) {
int r;
int stat_verify_directory(const struct stat *st);
int fd_verify_directory(int fd);
-/* glibc and the Linux kernel have different ideas about the major/minor size. These calls will check whether the
- * specified major is valid by the Linux kernel's standards, not by glibc's. Linux has 20bits of minor, and 12 bits of
- * major space. See MINORBITS in linux/kdev_t.h in the kernel sources. (If you wonder why we define _y here, instead of
- * comparing directly >= 0: it's to trick out -Wtype-limits, which would otherwise complain if the type is unsigned, as
- * such a test would be pointless in such a case.) */
-
-#define DEVICE_MAJOR_VALID(x) \
- ({ \
- typeof(x) _x = (x), _y = 0; \
- _x >= _y && _x < (UINT32_C(1) << 12); \
- \
- })
-
-#define DEVICE_MINOR_VALID(x) \
- ({ \
- typeof(x) _x = (x), _y = 0; \
- _x >= _y && _x < (UINT32_C(1) << 20); \
- })
-
-int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret);
-int device_path_make_canonical(mode_t mode, dev_t devno, char **ret);
-int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno);
-
int proc_mounted(void);
bool stat_inode_same(const struct stat *a, const struct stat *b);
struct new_statx nsx; \
} var
#endif
-
-static inline bool devid_set_and_equal(dev_t a, dev_t b) {
- /* Returns true if a and b definitely refer to the same device. If either is zero, this means "don't
- * know" and we'll return false */
- return a == b && a != 0;
-}
#include "alloc-util.h"
#include "def.h"
+#include "devnum-util.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "alloc-util.h"
#include "bootspec.h"
+#include "devnum-util.h"
#include "efi-api.h"
#include "efi-loader.h"
#include "efivars.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
-#include "stat-util.h"
#include "sync-util.h"
#include "terminal-util.h"
#include "util.h"
"Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n"
"Alternatively, use --path= to specify path to mount point.");
- if (esp_path && xbootldr_path && !devid_set_and_equal(esp_devid, xbootldr_devid)) /* in case the two paths refer to the same inode, suppress one */
+ if (esp_path && xbootldr_path && !devnum_set_and_equal(esp_devid, xbootldr_devid)) /* in case the two paths refer to the same inode, suppress one */
a = strv_new(esp_path, xbootldr_path);
else if (esp_path)
a = strv_new(esp_path);
#include "blkid-util.h"
#include "bootspec.h"
#include "copy.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "efi-api.h"
#include "efi-loader.h"
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would
* find the same entries twice. */
- bool same = esp_path && xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
+ bool same = esp_path && xbootldr_path && devnum_set_and_equal(esp_devid, xbootldr_devid);
r = boot_config_load(config, esp_path, same ? NULL : xbootldr_path);
if (r < 0)
#include "bpf-devices.h"
#include "bpf-program.h"
+#include "devnum-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "nulstr-util.h"
#include "parse-util.h"
#include "path-util.h"
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "cgroup-setup.h"
#include "cgroup-util.h"
#include "cgroup.h"
+#include "devnum-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "in-addr-prefix-util.h"
#include "procfs-util.h"
#include "restrict-ifaces.h"
#include "special.h"
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "device-util.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "dissect-image.h"
#include "dropin.h"
previous_devno = st.st_dev;
- r = quotactl_devno(QCMD_FIXED(Q_GETQUOTA, USRQUOTA), st.st_dev, uid, &req);
+ r = quotactl_devnum(QCMD_FIXED(Q_GETQUOTA, USRQUOTA), st.st_dev, uid, &req);
if (r < 0) {
if (ERRNO_IS_NOT_SUPPORTED(r))
log_debug_errno(r, "No UID quota support on %s, ignoring.", where);
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "chattr-util.h"
+#include "devnum-util.h"
#include "dm-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "process-util.h"
#include "random-util.h"
#include "resize-fs.h"
-#include "stat-util.h"
#include "strv.h"
#include "sync-util.h"
#include "tmpfile-util.h"
if (devno == 0)
return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system %s not backed by a block device.", path);
- r = quotactl_devno(QCMD_FIXED(Q_GETQUOTA, USRQUOTA), devno, h->uid, &req);
+ r = quotactl_devnum(QCMD_FIXED(Q_GETQUOTA, USRQUOTA), devno, h->uid, &req);
if (r < 0) {
if (ERRNO_IS_NOT_SUPPORTED(r))
return log_error_errno(r, "No UID quota support on %s.", path);
req.dqb_valid = QIF_BLIMITS;
req.dqb_bsoftlimit = req.dqb_bhardlimit = h->disk_size / QIF_DQBLKSIZE;
- r = quotactl_devno(QCMD_FIXED(Q_SETQUOTA, USRQUOTA), devno, h->uid, &req);
+ r = quotactl_devnum(QCMD_FIXED(Q_SETQUOTA, USRQUOTA), devno, h->uid, &req);
if (r < 0) {
if (r == -ESRCH)
return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "UID quota not available on %s.", path);
#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
#include "set.h"
#include "socket-util.h"
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
if (isempty(id))
return -EINVAL;
- r = parse_dev(id + 1, &devt);
+ r = parse_devnum(id + 1, &devt);
if (r < 0)
return r;
#include "bus-label.h"
#include "bus-polkit.h"
#include "bus-util.h"
+#include "devnum-util.h"
#include "fd-util.h"
#include "logind-brightness.h"
#include "logind-dbus.h"
#include "missing_capability.h"
#include "path-util.h"
#include "signal-util.h"
-#include "stat-util.h"
#include "strv.h"
#include "user-util.h"
#include "util.h"
#include "audit-util.h"
#include "bus-error.h"
#include "bus-util.h"
+#include "devnum-util.h"
#include "env-file.h"
#include "escape.h"
#include "fd-util.h"
break;
}
- k = parse_dev(word, &dev);
+ k = parse_devnum(word, &dev);
if (k < 0) {
r = k;
continue;
#include "bus-util.h"
#include "cap-list.h"
#include "cpu-set-util.h"
+#include "devnum-util.h"
#include "env-util.h"
#include "format-util.h"
#include "fs-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "btrfs-util.h"
#include "cryptsetup-util.h"
#include "device-nodes.h"
+#include "devnum-util.h"
#include "dissect-image.h"
#include "escape.h"
#include "fd-util.h"
#include "conf-parser.h"
#include "cryptsetup-util.h"
#include "def.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "efivars.h"
#include "errno-util.h"
#include "resize-fs.h"
#include "sort-util.h"
#include "specifier.h"
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
if (r < 0)
return log_error_errno(r, "Failed to read %s: %m", q);
- r = parse_dev(t, &sl);
+ r = parse_devnum(t, &sl);
if (r < 0) {
log_debug_errno(r, "Failed to parse %s, ignoring: %m", q);
continue;
#include "alloc-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "missing_magic.h"
#include "parse-util.h"
-#include "stat-util.h"
int block_get_whole_disk(dev_t d, dev_t *ret) {
char p[SYS_BLOCK_PATH_MAX("/partition")];
if (r < 0)
return r;
- r = parse_dev(s, &devt);
+ r = parse_devnum(s, &devt);
if (r < 0)
return r;
if (r < 0)
return r;
- r = parse_dev(t, &devt);
+ r = parse_devnum(t, &devt);
if (r < 0)
return -EINVAL;
#include "bootspec.h"
#include "bootspec-fundamental.h"
#include "conf-files.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "efi-loader.h"
#include "env-file.h"
#include "pe-header.h"
#include "recurse-dir.h"
#include "sort-util.h"
-#include "stat-util.h"
#include "strv.h"
#include "unaligned.h"
return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
/* If both paths actually refer to the same inode, suppress the xbootldr path */
- if (esp_where && xbootldr_where && devid_set_and_equal(esp_devid, xbootldr_devid))
+ if (esp_where && xbootldr_where && devnum_set_and_equal(esp_devid, xbootldr_devid))
xbootldr_where = mfree(xbootldr_where);
return boot_config_load(config, esp_where, xbootldr_where);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/magic.h>
+#include <sys/vfs.h>
#include "sd-device.h"
#include "alloc-util.h"
#include "blkid-util.h"
+#include "devnum-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "find-esp.h"
#include "alloc-util.h"
#include "blockdev-util.h"
#include "device-util.h"
+#include "devnum-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "fd-util.h"
r = read_one_line_file(sysfs, &buffer);
if (r < 0)
return r;
- r = parse_dev(buffer, &devno);
+ r = parse_devnum(buffer, &devno);
if (r < 0)
return r;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/quota.h>
+#include <sys/stat.h>
#include "alloc-util.h"
#include "blockdev-util.h"
+#include "devnum-util.h"
#include "quota-util.h"
-#include "stat-util.h"
-int quotactl_devno(int cmd, dev_t devno, int id, void *addr) {
+int quotactl_devnum(int cmd, dev_t devnum, int id, void *addr) {
_cleanup_free_ char *devnode = NULL;
int r;
/* Like quotactl() but takes a dev_t instead of a path to a device node, and fixes caddr_t → void*,
* like we should, today */
- r = device_path_make_major_minor(S_IFBLK, devno, &devnode);
+ r = device_path_make_major_minor(S_IFBLK, devnum, &devnode);
if (r < 0)
return r;
if (devno == 0) /* Doesn't have a block device */
return -ENODEV;
- return quotactl_devno(cmd, devno, id, addr);
+ return quotactl_devnum(cmd, devno, id, addr);
}
return (int) QCMD(cmd, type);
}
-int quotactl_devno(int cmd, dev_t devno, int id, void *addr);
+int quotactl_devnum(int cmd, dev_t devnum, int id, void *addr);
int quotactl_path(int cmd, const char *path, int id, void *addr);
#include "btrfs-util.h"
#include "conf-parser.h"
#include "def.h"
+#include "devnum-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
-#include "parse-util.h"
#include "path-util.h"
#include "sleep-config.h"
#include "stat-util.h"
if (r < 0)
return log_debug_errno(r, "Error reading /sys/power/resume: %m");
- r = parse_dev(resume_str, &resume);
+ r = parse_devnum(resume_str, &resume);
if (r < 0)
return log_debug_errno(r, "Error parsing /sys/power/resume device: %s: %m", resume_str);
#include "capability-util.h"
#include "chase-symlinks.h"
+#include "devnum-util.h"
#include "discover-image.h"
#include "dissect-image.h"
#include "env-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "sort-util.h"
-#include "stat-util.h"
#include "terminal-util.h"
#include "user-util.h"
#include "verbs.h"
if (r < 0)
return log_error_errno(r, "Failed to determine whether hierarchy '%s' contains '.systemd-sysext/dev': %m", p);
- r = parse_dev(buf, &dev);
+ r = parse_devnum(buf, &dev);
if (r < 0)
return log_error_errno(r, "Failed to parse device major/minor stored in '.systemd-sysext/dev' file on '%s': %m", p);
#include "alloc-util.h"
#include "blockdev-util.h"
#include "chase-symlinks.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "env-util.h"
#include "fd-util.h"
#include "macro.h"
#include "process-util.h"
#include "sort-util.h"
-#include "stat-util.h"
#include "string-table.h"
#include "sysupdate-cache.h"
#include "sysupdate-instance.h"
[files('test-stat-util.c')],
+ [files('test-devnum-util.c')],
+
[files('test-os-util.c')],
[files('test-libcrypt-util.c'),
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <sys/stat.h>
+
+#include "devnum-util.h"
+#include "path-util.h"
+#include "stat-util.h"
+#include "tests.h"
+
+TEST(parse_devnum) {
+ dev_t dev;
+
+ assert_se(parse_devnum("", &dev) == -EINVAL);
+ assert_se(parse_devnum("junk", &dev) == -EINVAL);
+ assert_se(parse_devnum("0", &dev) == -EINVAL);
+ assert_se(parse_devnum("5", &dev) == -EINVAL);
+ assert_se(parse_devnum("5:", &dev) == -EINVAL);
+ assert_se(parse_devnum(":5", &dev) == -EINVAL);
+ assert_se(parse_devnum("-1:-1", &dev) == -EINVAL);
+#if SIZEOF_DEV_T < 8
+ assert_se(parse_devnum("4294967295:4294967295", &dev) == -EINVAL);
+#endif
+ assert_se(parse_devnum("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11);
+ assert_se(parse_devnum("0:0", &dev) >= 0 && major(dev) == 0 && minor(dev) == 0);
+}
+
+TEST(device_major_minor_valid) {
+ /* on glibc dev_t is 64bit, even though in the kernel it is only 32bit */
+ assert_cc(sizeof(dev_t) == sizeof(uint64_t));
+
+ assert_se(DEVICE_MAJOR_VALID(0U));
+ assert_se(DEVICE_MINOR_VALID(0U));
+
+ assert_se(DEVICE_MAJOR_VALID(1U));
+ assert_se(DEVICE_MINOR_VALID(1U));
+
+ assert_se(!DEVICE_MAJOR_VALID(-1U));
+ assert_se(!DEVICE_MINOR_VALID(-1U));
+
+ assert_se(DEVICE_MAJOR_VALID(1U << 10));
+ assert_se(DEVICE_MINOR_VALID(1U << 10));
+
+ assert_se(DEVICE_MAJOR_VALID((1U << 12) - 1));
+ assert_se(DEVICE_MINOR_VALID((1U << 20) - 1));
+
+ assert_se(!DEVICE_MAJOR_VALID((1U << 12)));
+ assert_se(!DEVICE_MINOR_VALID((1U << 20)));
+
+ assert_se(!DEVICE_MAJOR_VALID(1U << 25));
+ assert_se(!DEVICE_MINOR_VALID(1U << 25));
+
+ assert_se(!DEVICE_MAJOR_VALID(UINT32_MAX));
+ assert_se(!DEVICE_MINOR_VALID(UINT32_MAX));
+
+ assert_se(!DEVICE_MAJOR_VALID(UINT64_MAX));
+ assert_se(!DEVICE_MINOR_VALID(UINT64_MAX));
+
+ assert_se(DEVICE_MAJOR_VALID(major(0)));
+ assert_se(DEVICE_MINOR_VALID(minor(0)));
+}
+
+static void test_device_path_make_canonical_one(const char *path) {
+ _cleanup_free_ char *resolved = NULL, *raw = NULL;
+ struct stat st;
+ dev_t devno;
+ mode_t mode;
+ int r;
+
+ log_debug("> %s", path);
+
+ if (stat(path, &st) < 0) {
+ assert_se(errno == ENOENT);
+ log_notice("Path %s not found, skipping test", path);
+ return;
+ }
+
+ r = device_path_make_canonical(st.st_mode, st.st_rdev, &resolved);
+ if (r == -ENOENT) {
+ /* maybe /dev/char/x:y and /dev/block/x:y are missing in this test environment, because we
+ * run in a container or so? */
+ log_notice("Device %s cannot be resolved, skipping test", path);
+ return;
+ }
+
+ assert_se(r >= 0);
+ assert_se(path_equal(path, resolved));
+
+ assert_se(device_path_make_major_minor(st.st_mode, st.st_rdev, &raw) >= 0);
+ assert_se(device_path_parse_major_minor(raw, &mode, &devno) >= 0);
+
+ assert_se(st.st_rdev == devno);
+ assert_se((st.st_mode & S_IFMT) == (mode & S_IFMT));
+}
+
+TEST(device_path_make_canonical) {
+ test_device_path_make_canonical_one("/dev/null");
+ test_device_path_make_canonical_one("/dev/zero");
+ test_device_path_make_canonical_one("/dev/full");
+ test_device_path_make_canonical_one("/dev/random");
+ test_device_path_make_canonical_one("/dev/urandom");
+ test_device_path_make_canonical_one("/dev/tty");
+
+ if (is_device_node("/run/systemd/inaccessible/blk") > 0) {
+ test_device_path_make_canonical_one("/run/systemd/inaccessible/chr");
+ test_device_path_make_canonical_one("/run/systemd/inaccessible/blk");
+ }
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);
assert_se(parse_nice("+20", &n) == -ERANGE);
}
-TEST(parse_dev) {
- dev_t dev;
-
- assert_se(parse_dev("", &dev) == -EINVAL);
- assert_se(parse_dev("junk", &dev) == -EINVAL);
- assert_se(parse_dev("0", &dev) == -EINVAL);
- assert_se(parse_dev("5", &dev) == -EINVAL);
- assert_se(parse_dev("5:", &dev) == -EINVAL);
- assert_se(parse_dev(":5", &dev) == -EINVAL);
- assert_se(parse_dev("-1:-1", &dev) == -EINVAL);
-#if SIZEOF_DEV_T < 8
- assert_se(parse_dev("4294967295:4294967295", &dev) == -EINVAL);
-#endif
- assert_se(parse_dev("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11);
- assert_se(parse_dev("0:0", &dev) >= 0 && major(dev) == 0 && minor(dev) == 0);
-}
-
TEST(parse_errno) {
assert_se(parse_errno("EILSEQ") == EILSEQ);
assert_se(parse_errno("EINVAL") == EINVAL);
assert_se(IN_SET(fd_is_ns(fd, CLONE_NEWNET), 1, -EUCLEAN));
}
-TEST(device_major_minor_valid) {
- /* on glibc dev_t is 64bit, even though in the kernel it is only 32bit */
- assert_cc(sizeof(dev_t) == sizeof(uint64_t));
-
- assert_se(DEVICE_MAJOR_VALID(0U));
- assert_se(DEVICE_MINOR_VALID(0U));
-
- assert_se(DEVICE_MAJOR_VALID(1U));
- assert_se(DEVICE_MINOR_VALID(1U));
-
- assert_se(!DEVICE_MAJOR_VALID(-1U));
- assert_se(!DEVICE_MINOR_VALID(-1U));
-
- assert_se(DEVICE_MAJOR_VALID(1U << 10));
- assert_se(DEVICE_MINOR_VALID(1U << 10));
-
- assert_se(DEVICE_MAJOR_VALID((1U << 12) - 1));
- assert_se(DEVICE_MINOR_VALID((1U << 20) - 1));
-
- assert_se(!DEVICE_MAJOR_VALID((1U << 12)));
- assert_se(!DEVICE_MINOR_VALID((1U << 20)));
-
- assert_se(!DEVICE_MAJOR_VALID(1U << 25));
- assert_se(!DEVICE_MINOR_VALID(1U << 25));
-
- assert_se(!DEVICE_MAJOR_VALID(UINT32_MAX));
- assert_se(!DEVICE_MINOR_VALID(UINT32_MAX));
-
- assert_se(!DEVICE_MAJOR_VALID(UINT64_MAX));
- assert_se(!DEVICE_MINOR_VALID(UINT64_MAX));
-
- assert_se(DEVICE_MAJOR_VALID(major(0)));
- assert_se(DEVICE_MINOR_VALID(minor(0)));
-}
-
-static void test_device_path_make_canonical_one(const char *path) {
- _cleanup_free_ char *resolved = NULL, *raw = NULL;
- struct stat st;
- dev_t devno;
- mode_t mode;
- int r;
-
- log_debug("> %s", path);
-
- if (stat(path, &st) < 0) {
- assert_se(errno == ENOENT);
- log_notice("Path %s not found, skipping test", path);
- return;
- }
-
- r = device_path_make_canonical(st.st_mode, st.st_rdev, &resolved);
- if (r == -ENOENT) {
- /* maybe /dev/char/x:y and /dev/block/x:y are missing in this test environment, because we
- * run in a container or so? */
- log_notice("Device %s cannot be resolved, skipping test", path);
- return;
- }
-
- assert_se(r >= 0);
- assert_se(path_equal(path, resolved));
-
- assert_se(device_path_make_major_minor(st.st_mode, st.st_rdev, &raw) >= 0);
- assert_se(device_path_parse_major_minor(raw, &mode, &devno) >= 0);
-
- assert_se(st.st_rdev == devno);
- assert_se((st.st_mode & S_IFMT) == (mode & S_IFMT));
-}
-
-TEST(device_path_make_canonical) {
- test_device_path_make_canonical_one("/dev/null");
- test_device_path_make_canonical_one("/dev/zero");
- test_device_path_make_canonical_one("/dev/full");
- test_device_path_make_canonical_one("/dev/random");
- test_device_path_make_canonical_one("/dev/urandom");
- test_device_path_make_canonical_one("/dev/tty");
-
- if (is_device_node("/run/systemd/inaccessible/blk") > 0) {
- test_device_path_make_canonical_one("/run/systemd/inaccessible/chr");
- test_device_path_make_canonical_one("/run/systemd/inaccessible/blk");
- }
-}
-
TEST(dir_is_empty) {
_cleanup_(rm_rf_physical_and_freep) char *empty_dir = NULL;
_cleanup_free_ char *j = NULL, *jj = NULL;
#include "conf-files.h"
#include "copy.h"
#include "def.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "dissect-image.h"
#include "env-util.h"
#include "set.h"
#include "sort-util.h"
#include "specifier.h"
-#include "stat-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Device file requires argument.");
}
- r = parse_dev(i.argument, &i.major_minor);
+ r = parse_devnum(i.argument, &i.major_minor);
if (r < 0) {
*invalid_config = true;
return log_syntax(NULL, LOG_ERR, fname, line, r, "Can't parse device file major/minor '%s'.", i.argument);
#include "alloc-util.h"
#include "device-private.h"
#include "device-util.h"
+#include "devnum-util.h"
#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
+#include "devnum-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "main-func.h"
#include "process-util.h"
#include "signal-util.h"
#include "sort-util.h"
-#include "stat-util.h"
#include "strv.h"
#include "time-util.h"
#include "udevadm.h"
#include "alloc-util.h"
#include "blockdev-util.h"
#include "chase-symlinks.h"
+#include "devnum-util.h"
#include "escape.h"
#include "main-func.h"
#include "mkdir.h"
#include "mount-util.h"
#include "mountpoint-util.h"
#include "path-util.h"
-#include "stat-util.h"
#include "string-util.h"
#include "volatile-util.h"