diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-10-07 15:59:51 +0300 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-10-07 15:59:51 +0300 |
commit | f74431288aec78ffdd05be9a519eab3dbe1c4f81 (patch) | |
tree | 02ddece6f545771996743f09d0f4ee0d42a64e80 /src | |
parent | 5530caa20b9688bad0bceedb4d9df5df8ad96299 (diff) | |
parent | 9818005de6cc6f525be8aa62a2b8593a7c72e798 (diff) |
Merge pull request #1485 from jsynacek/machine-long-filename-v5
import: hash URL in paths if they are too long
Diffstat (limited to 'src')
-rw-r--r-- | src/import/pull-common.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/src/import/pull-common.c b/src/import/pull-common.c index 38201e46e1..1ddb48e03f 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -31,8 +31,10 @@ #include "pull-common.h" #include "process-util.h" #include "signal-util.h" +#include "siphash24.h" #define FILENAME_ESCAPE "/.#\"\'" +#define HASH_URL_THRESHOLD_LENGTH (_POSIX_PATH_MAX - 16) int pull_find_old_etags( const char *url, @@ -149,8 +151,21 @@ int pull_make_local_copy(const char *final, const char *image_root, const char * return 0; } +static int hash_url(const char *url, char **ret) { + uint64_t h; + static const sd_id128_t k = SD_ID128_ARRAY(df,89,16,87,01,cc,42,30,98,ab,4a,19,a6,a5,63,4f); + + assert(url); + + siphash24((uint8_t *) &h, url, strlen(url), k.bytes); + if (asprintf(ret, "%"PRIx64, h) < 0) + return -ENOMEM; + + return 0; +} + int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret) { - _cleanup_free_ char *escaped_url = NULL; + _cleanup_free_ char *escaped_url = NULL, *escaped_etag = NULL; char *path; assert(url); @@ -164,18 +179,35 @@ int pull_make_path(const char *url, const char *etag, const char *image_root, co return -ENOMEM; if (etag) { - _cleanup_free_ char *escaped_etag = NULL; - escaped_etag = xescape(etag, FILENAME_ESCAPE); if (!escaped_etag) return -ENOMEM; + } - path = strjoin(image_root, "/", strempty(prefix), escaped_url, ".", escaped_etag, strempty(suffix), NULL); - } else - path = strjoin(image_root, "/", strempty(prefix), escaped_url, strempty(suffix), NULL); + path = strjoin(image_root, "/", strempty(prefix), escaped_url, escaped_etag ? "." : "", + strempty(escaped_etag), strempty(suffix), NULL); if (!path) return -ENOMEM; + /* URLs might make the path longer than the maximum allowed length for a file name. + * When that happens, a URL hash is used instead. Paths returned by this function + * can be later used with tempfn_random() which adds 16 bytes to the resulting name. */ + if (strlen(path) >= HASH_URL_THRESHOLD_LENGTH) { + _cleanup_free_ char *hash = NULL; + int r; + + free(path); + + r = hash_url(url, &hash); + if (r < 0) + return r; + + path = strjoin(image_root, "/", strempty(prefix), hash, escaped_etag ? "." : "", + strempty(escaped_etag), strempty(suffix), NULL); + if (!path) + return -ENOMEM; + } + *ret = path; return 0; } |