diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-06-02 15:33:34 +0200 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-06-04 08:51:31 +0200 |
commit | e64943363a8dd8bd320c2b633478be8befd1af5c (patch) | |
tree | 6ba8b729d8859412ac7288997ff98c16736dba3d | |
parent | util: expose urlsafe_base64char() (diff) | |
download | systemd-e64943363a8dd8bd320c2b633478be8befd1af5c.tar.xz systemd-e64943363a8dd8bd320c2b633478be8befd1af5c.zip |
udev: use hashed path as a filename to save devlink
-rw-r--r-- | src/udev/udev-node.c | 44 | ||||
-rw-r--r-- | src/udev/udev-node.h | 2 |
2 files changed, 31 insertions, 15 deletions
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index a6abaa1a9d..b3bbbaa4d8 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -7,6 +7,8 @@ #include <sys/stat.h> #include <unistd.h> +#include "sd-id128.h" + #include "alloc-util.h" #include "device-nodes.h" #include "device-private.h" @@ -15,6 +17,7 @@ #include "fd-util.h" #include "format-util.h" #include "fs-util.h" +#include "hexdecoct.h" #include "mkdir.h" #include "path-util.h" #include "selinux-util.h" @@ -27,6 +30,7 @@ #include "user-util.h" #define LINK_UPDATE_MAX_RETRIES 128 +#define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f) static int node_symlink(sd_device *dev, const char *node, const char *slink) { _cleanup_free_ char *slink_dirname = NULL, *target = NULL; @@ -191,45 +195,54 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir, return 0; } -static size_t escape_path(const char *src, char *dest, size_t size) { +size_t udev_node_escape_path(const char *src, char *dest, size_t size) { size_t i, j; + uint64_t h; assert(src); assert(dest); for (i = 0, j = 0; src[i] != '\0'; i++) { if (src[i] == '/') { - if (j+4 >= size) { - j = 0; - break; - } + if (j+4 >= size) + goto toolong; memcpy(&dest[j], "\\x2f", 4); j += 4; } else if (src[i] == '\\') { - if (j+4 >= size) { - j = 0; - break; - } + if (j+4 >= size) + goto toolong; memcpy(&dest[j], "\\x5c", 4); j += 4; } else { - if (j+1 >= size) { - j = 0; - break; - } + if (j+1 >= size) + goto toolong; dest[j] = src[i]; j++; } } dest[j] = '\0'; return j; + +toolong: + /* If the input path is too long to encode as a filename, then let's suffix with a string + * generated from the hash of the path. */ + + h = siphash24_string(src, UDEV_NODE_HASH_KEY.bytes); + + assert(size >= 12); + + for (unsigned k = 0; k <= 10; k++) + dest[size - k - 2] = urlsafe_base64char((h >> (k * 6)) & 63); + + dest[size - 1] = '\0'; + return size - 1; } /* manage "stack of names" with possibly specified device priorities */ static int link_update(sd_device *dev, const char *slink, bool add) { _cleanup_free_ char *filename = NULL, *dirname = NULL; const char *slink_name, *id; - char name_enc[PATH_MAX]; + char name_enc[NAME_MAX+1]; int i, r, retries; assert(dev); @@ -244,10 +257,11 @@ static int link_update(sd_device *dev, const char *slink, bool add) { if (r < 0) return log_device_debug_errno(dev, r, "Failed to get device id: %m"); - escape_path(slink_name, name_enc, sizeof(name_enc)); + (void) udev_node_escape_path(slink_name, name_enc, sizeof(name_enc)); dirname = path_join("/run/udev/links/", name_enc); if (!dirname) return log_oom(); + filename = path_join(dirname, id); if (!filename) return log_oom(); diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h index 84c7e4567f..2349f9c471 100644 --- a/src/udev/udev-node.h +++ b/src/udev/udev-node.h @@ -13,3 +13,5 @@ int udev_node_add(sd_device *dev, bool apply, OrderedHashmap *seclabel_list); int udev_node_remove(sd_device *dev); int udev_node_update_old_links(sd_device *dev, sd_device *dev_old); + +size_t udev_node_escape_path(const char *src, char *dest, size_t size); |