Merge pull request #22759 from msekletar/issue-18077-long-sysfs-paths-hashing
Create "hashed" unit names from long paths
This commit is contained in:
+12
-11
@@ -10,17 +10,18 @@
|
||||
#include "string-util-fundamental.h"
|
||||
|
||||
/* What is interpreted as whitespace? */
|
||||
#define WHITESPACE " \t\n\r"
|
||||
#define NEWLINE "\n\r"
|
||||
#define QUOTES "\"\'"
|
||||
#define COMMENTS "#;"
|
||||
#define GLOB_CHARS "*?["
|
||||
#define DIGITS "0123456789"
|
||||
#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
|
||||
#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
|
||||
#define ALPHANUMERICAL LETTERS DIGITS
|
||||
#define HEXDIGITS DIGITS "abcdefABCDEF"
|
||||
#define WHITESPACE " \t\n\r"
|
||||
#define NEWLINE "\n\r"
|
||||
#define QUOTES "\"\'"
|
||||
#define COMMENTS "#;"
|
||||
#define GLOB_CHARS "*?["
|
||||
#define DIGITS "0123456789"
|
||||
#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
|
||||
#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
|
||||
#define ALPHANUMERICAL LETTERS DIGITS
|
||||
#define HEXDIGITS DIGITS "abcdefABCDEF"
|
||||
#define LOWERCASE_HEXDIGITS DIGITS "abcdef"
|
||||
|
||||
static inline char* strstr_ptr(const char *haystack, const char *needle) {
|
||||
if (!haystack || !needle)
|
||||
|
||||
+84
-2
@@ -5,12 +5,17 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "glob-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "memory-util.h"
|
||||
#include "path-util.h"
|
||||
#include "random-util.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "special.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "unit-name.h"
|
||||
@@ -31,6 +36,9 @@
|
||||
VALID_CHARS_WITH_AT \
|
||||
"[]!-*?"
|
||||
|
||||
#define LONG_UNIT_NAME_HASH_KEY SD_ID128_MAKE(ec,f2,37,fb,58,32,4a,32,84,9f,06,9b,0d,21,eb,9a)
|
||||
#define UNIT_NAME_HASH_LENGTH_CHARS 16
|
||||
|
||||
bool unit_name_is_valid(const char *n, UnitNameFlags flags) {
|
||||
const char *e, *i, *at;
|
||||
|
||||
@@ -507,6 +515,68 @@ int unit_name_template(const char *f, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool unit_name_is_hashed(const char *name) {
|
||||
char *s;
|
||||
|
||||
if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
|
||||
return false;
|
||||
|
||||
assert_se(s = strrchr(name, '.'));
|
||||
|
||||
if (s - name < UNIT_NAME_HASH_LENGTH_CHARS + 1)
|
||||
return false;
|
||||
|
||||
s -= UNIT_NAME_HASH_LENGTH_CHARS;
|
||||
if (s[-1] != '_')
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < UNIT_NAME_HASH_LENGTH_CHARS; i++)
|
||||
if (!strchr(LOWERCASE_HEXDIGITS, s[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int unit_name_hash_long(const char *name, char **ret) {
|
||||
_cleanup_free_ char *n = NULL, *hash = NULL;
|
||||
char *suffix;
|
||||
le64_t h;
|
||||
size_t len;
|
||||
|
||||
if (strlen(name) < UNIT_NAME_MAX)
|
||||
return -EMSGSIZE;
|
||||
|
||||
suffix = strrchr(name, '.');
|
||||
if (!suffix)
|
||||
return -EINVAL;
|
||||
|
||||
if (unit_type_from_string(suffix+1) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
h = htole64(siphash24_string(name, LONG_UNIT_NAME_HASH_KEY.bytes));
|
||||
|
||||
hash = hexmem(&h, sizeof(h));
|
||||
if (!hash)
|
||||
return -ENOMEM;
|
||||
|
||||
assert_se(strlen(hash) == UNIT_NAME_HASH_LENGTH_CHARS);
|
||||
|
||||
len = UNIT_NAME_MAX - 1 - strlen(suffix+1) - UNIT_NAME_HASH_LENGTH_CHARS - 2;
|
||||
assert(len > 0 && len < UNIT_NAME_MAX);
|
||||
|
||||
n = strndup(name, len);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strextend(&n, "_", hash, suffix))
|
||||
return -ENOMEM;
|
||||
assert_se(unit_name_is_valid(n, UNIT_NAME_PLAIN));
|
||||
|
||||
*ret = TAKE_PTR(n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unit_name_from_path(const char *path, const char *suffix, char **ret) {
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
int r;
|
||||
@@ -526,8 +596,17 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret) {
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
if (strlen(s) >= UNIT_NAME_MAX) /* Return a slightly more descriptive error for this specific condition */
|
||||
return -ENAMETOOLONG;
|
||||
if (strlen(s) >= UNIT_NAME_MAX) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
|
||||
log_debug("Unit name \"%s\" too long, falling back to hashed unit name.", s);
|
||||
|
||||
r = unit_name_hash_long(s, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
free_and_replace(s, n);
|
||||
}
|
||||
|
||||
/* Refuse if this for some other reason didn't result in a valid name */
|
||||
if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
|
||||
@@ -581,6 +660,9 @@ int unit_name_to_path(const char *name, char **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (unit_name_is_hashed(name))
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
return unit_name_path_unescape(prefix, ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ int unit_name_replace_instance(const char *f, const char *i, char **ret);
|
||||
|
||||
int unit_name_template(const char *f, char **ret);
|
||||
|
||||
int unit_name_hash_long(const char *name, char **ret);
|
||||
bool unit_name_is_hashed(const char *name);
|
||||
|
||||
int unit_name_from_path(const char *path, const char *suffix, char **ret);
|
||||
int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret);
|
||||
int unit_name_to_path(const char *name, char **ret);
|
||||
|
||||
Reference in New Issue
Block a user