summaryrefslogtreecommitdiff
path: root/src/udev/udev-node.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-04-06 02:31:19 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-04-06 14:52:36 +0900
commit26dd37f6d565dd28d15b3401491589b5a7c86ecb (patch)
tree4846719beeaa947852e578d659556bbd22315f7a /src/udev/udev-node.c
parente5ddfe3ec586c9ab174d39f4b6202155d92d24e4 (diff)
downloadsystemd-26dd37f6d565dd28d15b3401491589b5a7c86ecb.tar.gz
udev: move apply_static_dev_perms() to udev-node.c
and make it internally use udev_node_apply_permissions_impl().
Diffstat (limited to 'src/udev/udev-node.c')
-rw-r--r--src/udev/udev-node.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 493feffe00..deacbc31c5 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -13,6 +13,7 @@
#include "device-private.h"
#include "device-util.h"
#include "dirent-util.h"
+#include "escape.h"
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
@@ -718,3 +719,64 @@ int udev_node_apply_permissions(
return udev_node_apply_permissions_impl(dev, node_fd, devnode, apply_mac, mode, uid, gid, seclabel_list);
}
+
+int static_node_apply_permissions(
+ const char *name,
+ mode_t mode,
+ uid_t uid,
+ gid_t gid,
+ char **tags) {
+
+ _cleanup_free_ char *unescaped_filename = NULL;
+ _cleanup_close_ int node_fd = -1;
+ const char *devnode;
+ struct stat stats;
+ int r;
+
+ assert(name);
+
+ if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID && !tags)
+ return 0;
+
+ devnode = strjoina("/dev/", name);
+
+ node_fd = open(devnode, O_PATH|O_CLOEXEC);
+ if (node_fd < 0) {
+ if (errno != ENOENT)
+ return log_error_errno(errno, "Failed to open %s: %m", devnode);
+ return 0;
+ }
+
+ if (fstat(node_fd, &stats) < 0)
+ return log_error_errno(errno, "Failed to stat %s: %m", devnode);
+
+ if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) {
+ log_warning("%s is neither block nor character device, ignoring.", devnode);
+ return 0;
+ }
+
+ if (!strv_isempty(tags)) {
+ unescaped_filename = xescape(name, "/.");
+ if (!unescaped_filename)
+ return log_oom();
+ }
+
+ /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */
+ STRV_FOREACH(t, tags) {
+ _cleanup_free_ char *p = NULL;
+
+ p = path_join("/run/udev/static_node-tags/", *t, unescaped_filename);
+ if (!p)
+ return log_oom();
+
+ r = mkdir_parents(p, 0755);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create parent directory for %s: %m", p);
+
+ r = symlink(devnode, p);
+ if (r < 0 && errno != EEXIST)
+ return log_error_errno(errno, "Failed to create symlink %s -> %s: %m", p, devnode);
+ }
+
+ return udev_node_apply_permissions_impl(NULL, node_fd, devnode, false, mode, uid, gid, NULL);
+}