basic: split out blockdev-util.[ch] from util.h
With three functions it makes sense to split this out now.
This commit is contained in:
parent
0adc28ceec
commit
18c528e99f
199
src/basic/blockdev-util.c
Normal file
199
src/basic/blockdev-util.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "btrfs-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "missing.h"
|
||||
#include "stat-util.h"
|
||||
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret) {
|
||||
char p[SYS_BLOCK_PATH_MAX("/partition")];
|
||||
_cleanup_free_ char *s = NULL;
|
||||
unsigned n, m;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* If it has a queue this is good enough for us */
|
||||
xsprintf_sys_block_path(p, "/queue", d);
|
||||
if (access(p, F_OK) >= 0) {
|
||||
*ret = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If it is a partition find the originating device */
|
||||
xsprintf_sys_block_path(p, "/partition", d);
|
||||
if (access(p, F_OK) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
/* Get parent dev_t */
|
||||
xsprintf_sys_block_path(p, "/../dev", d);
|
||||
r = read_one_line_file(p, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sscanf(s, "%u:%u", &m, &n);
|
||||
if (r != 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Only return this if it is really good enough for us. */
|
||||
xsprintf_sys_block_path(p, "/queue", makedev(m, n));
|
||||
if (access(p, F_OK) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
*ret = makedev(m, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_block_device(const char *path, dev_t *dev) {
|
||||
struct stat st;
|
||||
struct statfs sfs;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Get's the block device directly backing a file system. If
|
||||
* the block device is encrypted, returns the device mapper
|
||||
* block device. */
|
||||
|
||||
if (lstat(path, &st))
|
||||
return -errno;
|
||||
|
||||
if (major(st.st_dev) != 0) {
|
||||
*dev = st.st_dev;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (statfs(path, &sfs) < 0)
|
||||
return -errno;
|
||||
|
||||
if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
|
||||
return btrfs_get_block_device(path, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_block_device_harder(const char *path, dev_t *dev) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
char p[SYS_BLOCK_PATH_MAX("/slaves")];
|
||||
struct dirent *de, *found = NULL;
|
||||
const char *q;
|
||||
unsigned maj, min;
|
||||
dev_t dt;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Gets the backing block device for a file system, and
|
||||
* handles LUKS encrypted file systems, looking for its
|
||||
* immediate parent, if there is one. */
|
||||
|
||||
r = get_block_device(path, &dt);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
xsprintf_sys_block_path(p, "/slaves", dt);
|
||||
d = opendir(p);
|
||||
if (!d) {
|
||||
if (errno == ENOENT)
|
||||
goto fallback;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
|
||||
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
|
||||
continue;
|
||||
|
||||
if (found) {
|
||||
_cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
|
||||
|
||||
/* We found a device backed by multiple other devices. We don't really support automatic
|
||||
* discovery on such setups, with the exception of dm-verity partitions. In this case there are
|
||||
* two backing devices: the data partition and the hash partition. We are fine with such
|
||||
* setups, however, only if both partitions are on the same physical device. Hence, let's
|
||||
* verify this. */
|
||||
|
||||
u = strjoin(p, "/", de->d_name, "/../dev");
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
v = strjoin(p, "/", found->d_name, "/../dev");
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
|
||||
r = read_one_line_file(u, &a);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read %s: %m", u);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
r = read_one_line_file(v, &b);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read %s: %m", v);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Check if the parent device is the same. If not, then the two backing devices are on
|
||||
* different physical devices, and we don't support that. */
|
||||
if (!streq(a, b))
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
found = de;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto fallback;
|
||||
|
||||
q = strjoina(p, "/", found->d_name, "/dev");
|
||||
|
||||
r = read_one_line_file(q, &t);
|
||||
if (r == -ENOENT)
|
||||
goto fallback;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sscanf(t, "%u:%u", &maj, &min) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (maj == 0)
|
||||
goto fallback;
|
||||
|
||||
*dev = makedev(maj, min);
|
||||
return 1;
|
||||
|
||||
fallback:
|
||||
*dev = dt;
|
||||
return 1;
|
||||
}
|
38
src/basic/blockdev-util.h
Normal file
38
src/basic/blockdev-util.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
#define SYS_BLOCK_PATH_MAX(suffix) \
|
||||
(STRLEN("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen_ptr(suffix))
|
||||
#define xsprintf_sys_block_path(buf, suffix, devno) \
|
||||
xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix))
|
||||
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret);
|
||||
|
||||
int get_block_device(const char *path, dev_t *dev);
|
||||
|
||||
int get_block_device_harder(const char *path, dev_t *dev);
|
|
@ -38,6 +38,7 @@
|
|||
#endif
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "btrfs-ctree.h"
|
||||
#include "btrfs-util.h"
|
||||
#include "chattr-util.h"
|
||||
|
|
|
@ -29,11 +29,6 @@
|
|||
int encode_devnode_name(const char *str, char *str_enc, size_t len);
|
||||
int whitelisted_char_for_devnode(char c, const char *additional);
|
||||
|
||||
#define SYS_BLOCK_PATH_MAX(suffix) \
|
||||
(STRLEN("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen_ptr(suffix))
|
||||
#define xsprintf_sys_block_path(buf, suffix, devno) \
|
||||
xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix))
|
||||
|
||||
#define DEV_NUM_PATH_MAX \
|
||||
(STRLEN("/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t))
|
||||
#define xsprintf_dev_num_path(buf, type, devno) \
|
||||
|
|
|
@ -35,6 +35,8 @@ basic_sources_plain = files('''
|
|||
bitmap.c
|
||||
bitmap.h
|
||||
blkid-util.h
|
||||
blockdev-util.c
|
||||
blockdev-util.h
|
||||
bpf-program.c
|
||||
bpf-program.h
|
||||
btrfs-ctree.h
|
||||
|
@ -203,10 +205,10 @@ basic_sources_plain = files('''
|
|||
time-util.h
|
||||
umask-util.h
|
||||
unaligned.h
|
||||
unit-name.c
|
||||
unit-name.h
|
||||
unit-def.c
|
||||
unit-def.h
|
||||
unit-name.c
|
||||
unit-name.h
|
||||
user-util.c
|
||||
user-util.h
|
||||
utf8.c
|
||||
|
|
168
src/basic/util.c
168
src/basic/util.c
|
@ -118,45 +118,6 @@ int socket_from_display(const char *display, char **path) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret) {
|
||||
char p[SYS_BLOCK_PATH_MAX("/partition")];
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
unsigned n, m;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* If it has a queue this is good enough for us */
|
||||
xsprintf_sys_block_path(p, "/queue", d);
|
||||
if (access(p, F_OK) >= 0) {
|
||||
*ret = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If it is a partition find the originating device */
|
||||
xsprintf_sys_block_path(p, "/partition", d);
|
||||
if (access(p, F_OK) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
/* Get parent dev_t */
|
||||
xsprintf_sys_block_path(p, "/../dev", d);
|
||||
r = read_one_line_file(p, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sscanf(s, "%u:%u", &m, &n);
|
||||
if (r != 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Only return this if it is really good enough for us. */
|
||||
xsprintf_sys_block_path(p, "/queue", makedev(m, n));
|
||||
if (access(p, F_OK) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
*ret = makedev(m, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool kexec_loaded(void) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
|
@ -592,132 +553,3 @@ int version(void) {
|
|||
SYSTEMD_FEATURES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_block_device(const char *path, dev_t *dev) {
|
||||
struct stat st;
|
||||
struct statfs sfs;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Get's the block device directly backing a file system. If
|
||||
* the block device is encrypted, returns the device mapper
|
||||
* block device. */
|
||||
|
||||
if (lstat(path, &st))
|
||||
return -errno;
|
||||
|
||||
if (major(st.st_dev) != 0) {
|
||||
*dev = st.st_dev;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (statfs(path, &sfs) < 0)
|
||||
return -errno;
|
||||
|
||||
if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
|
||||
return btrfs_get_block_device(path, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_block_device_harder(const char *path, dev_t *dev) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
char p[SYS_BLOCK_PATH_MAX("/slaves")];
|
||||
struct dirent *de, *found = NULL;
|
||||
const char *q;
|
||||
unsigned maj, min;
|
||||
dev_t dt;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Gets the backing block device for a file system, and
|
||||
* handles LUKS encrypted file systems, looking for its
|
||||
* immediate parent, if there is one. */
|
||||
|
||||
r = get_block_device(path, &dt);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
xsprintf_sys_block_path(p, "/slaves", dt);
|
||||
d = opendir(p);
|
||||
if (!d) {
|
||||
if (errno == ENOENT)
|
||||
goto fallback;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
|
||||
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
|
||||
continue;
|
||||
|
||||
if (found) {
|
||||
_cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
|
||||
|
||||
/* We found a device backed by multiple other devices. We don't really support automatic
|
||||
* discovery on such setups, with the exception of dm-verity partitions. In this case there are
|
||||
* two backing devices: the data partition and the hash partition. We are fine with such
|
||||
* setups, however, only if both partitions are on the same physical device. Hence, let's
|
||||
* verify this. */
|
||||
|
||||
u = strjoin(p, "/", de->d_name, "/../dev");
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
v = strjoin(p, "/", found->d_name, "/../dev");
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
|
||||
r = read_one_line_file(u, &a);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read %s: %m", u);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
r = read_one_line_file(v, &b);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read %s: %m", v);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Check if the parent device is the same. If not, then the two backing devices are on
|
||||
* different physical devices, and we don't support that. */
|
||||
if (!streq(a, b))
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
found = de;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto fallback;
|
||||
|
||||
q = strjoina(p, "/", found->d_name, "/dev");
|
||||
|
||||
r = read_one_line_file(q, &t);
|
||||
if (r == -ENOENT)
|
||||
goto fallback;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sscanf(t, "%u:%u", &maj, &min) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (maj == 0)
|
||||
goto fallback;
|
||||
|
||||
*dev = makedev(maj, min);
|
||||
return 1;
|
||||
|
||||
fallback:
|
||||
*dev = dt;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -71,8 +71,6 @@ bool plymouth_running(void);
|
|||
bool display_is_local(const char *display) _pure_;
|
||||
int socket_from_display(const char *display, char **path);
|
||||
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret);
|
||||
|
||||
#define NULSTR_FOREACH(i, l) \
|
||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||
|
||||
|
@ -191,6 +189,3 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
|
|||
int update_reboot_parameter_and_warn(const char *param);
|
||||
|
||||
int version(void);
|
||||
|
||||
int get_block_device(const char *path, dev_t *dev);
|
||||
int get_block_device_harder(const char *path, dev_t *dev);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <fnmatch.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "bpf-firewall.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "cgroup.h"
|
||||
|
@ -307,7 +308,7 @@ static int lookup_block_device(const char *p, dev_t *dev) {
|
|||
|
||||
/* If this is a partition, try to get the originating
|
||||
* block device */
|
||||
block_get_whole_disk(*dev, dev);
|
||||
(void) block_get_whole_disk(*dev, dev);
|
||||
} else {
|
||||
log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
|
||||
return -ENODEV;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "libudev.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "def.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
|
@ -35,12 +36,12 @@
|
|||
#include "linux-3.13/dm-ioctl.h"
|
||||
#include "list.h"
|
||||
#include "mount-setup.h"
|
||||
#include "mount-util.h"
|
||||
#include "path-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "umount.h"
|
||||
#include "mount-util.h"
|
||||
#include "util.h"
|
||||
#include "virt.h"
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "alloc-util.h"
|
||||
#include "blkid-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "btrfs-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "dissect-image.h"
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
#include "blockdev-util.h"
|
||||
#include "crypt-util.h"
|
||||
#include "device-nodes.h"
|
||||
#include "dissect-image.h"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "architecture.h"
|
||||
#include "ask-password-api.h"
|
||||
#include "blkid-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "copy.h"
|
||||
#include "crypt-util.h"
|
||||
#include "def.h"
|
||||
|
|
Loading…
Reference in a new issue