]>
Commit | Line | Data |
---|---|---|
7176f06c LP |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | #pragma once | |
3 | ||
4 | #include <inttypes.h> | |
5 | #include <stdbool.h> | |
6 | #include <sys/types.h> | |
7 | ||
ec61371f LP |
8 | #include "stdio-util.h" |
9 | ||
7176f06c LP |
10 | int parse_devnum(const char *s, dev_t *ret); |
11 | ||
12 | /* glibc and the Linux kernel have different ideas about the major/minor size. These calls will check whether the | |
13 | * specified major is valid by the Linux kernel's standards, not by glibc's. Linux has 20bits of minor, and 12 bits of | |
14 | * major space. See MINORBITS in linux/kdev_t.h in the kernel sources. (If you wonder why we define _y here, instead of | |
15 | * comparing directly >= 0: it's to trick out -Wtype-limits, which would otherwise complain if the type is unsigned, as | |
16 | * such a test would be pointless in such a case.) */ | |
17 | ||
18 | #define DEVICE_MAJOR_VALID(x) \ | |
19 | ({ \ | |
20 | typeof(x) _x = (x), _y = 0; \ | |
21 | _x >= _y && _x < (UINT32_C(1) << 12); \ | |
22 | \ | |
23 | }) | |
24 | ||
25 | #define DEVICE_MINOR_VALID(x) \ | |
26 | ({ \ | |
27 | typeof(x) _x = (x), _y = 0; \ | |
28 | _x >= _y && _x < (UINT32_C(1) << 20); \ | |
29 | }) | |
30 | ||
31 | int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret); | |
4492b5d8 | 32 | int device_path_make_inaccessible(mode_t mode, char **ret); |
7176f06c LP |
33 | int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret); |
34 | int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devnum); | |
35 | ||
36 | static inline bool devnum_set_and_equal(dev_t a, dev_t b) { | |
37 | /* Returns true if a and b definitely refer to the same device. If either is zero, this means "don't | |
38 | * know" and we'll return false */ | |
39 | return a == b && a != 0; | |
40 | } | |
ec61371f LP |
41 | |
42 | /* Maximum string length for a major:minor string. (Note that DECIMAL_STR_MAX includes space for a trailing NUL) */ | |
43 | #define DEVNUM_STR_MAX (DECIMAL_STR_MAX(dev_t)-1+1+DECIMAL_STR_MAX(dev_t)) | |
44 | ||
45 | #define DEVNUM_FORMAT_STR "%u:%u" | |
46 | #define DEVNUM_FORMAT_VAL(d) major(d), minor(d) | |
47 | ||
48 | static inline char *format_devnum(dev_t d, char buf[static DEVNUM_STR_MAX]) { | |
49 | return ASSERT_PTR(snprintf_ok(buf, DEVNUM_STR_MAX, DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(d))); | |
50 | } | |
51 | ||
52 | #define FORMAT_DEVNUM(d) format_devnum((d), (char[DEVNUM_STR_MAX]) {}) | |
d80e2a1e LP |
53 | |
54 | static inline bool devnum_is_zero(dev_t d) { | |
55 | return major(d) == 0 && minor(d) == 0; | |
56 | } |