X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=lib%2Furl%2Furl.c;h=8a3d0db50ee6c38e5f39d8e2eb0ffe8e31928288;hp=4e4b9610cd96f1016a6d38aca78e258f5a97452c;hb=769fd76dc9bf3440999297ab943af49160df9c45;hpb=16ebe978aeced862dd877cfee81ac7604902fd55 diff --git a/lib/url/url.c b/lib/url/url.c index 4e4b961..8a3d0db 100644 --- a/lib/url/url.c +++ b/lib/url/url.c @@ -22,6 +22,7 @@ #define _GNU_SOURCE #include +#include #include #include "log/log.h" @@ -36,6 +37,7 @@ struct pb_scheme_info { enum pb_url_scheme scheme; const char *str; unsigned int str_len; + bool has_host; }; static const struct pb_scheme_info schemes[] = { @@ -43,36 +45,43 @@ static const struct pb_scheme_info schemes[] = { .scheme = pb_url_file, .str = "file", .str_len = sizeof("file") - 1, + .has_host = false, }, { .scheme = pb_url_ftp, .str = "ftp", .str_len = sizeof("ftp") - 1, + .has_host = true, }, { .scheme = pb_url_http, .str = "http", .str_len = sizeof("http") - 1, + .has_host = true, }, { .scheme = pb_url_https, .str = "https", .str_len = sizeof("https") - 1, + .has_host = true, }, { .scheme = pb_url_nfs, .str = "nfs", .str_len = sizeof("nfs") - 1, + .has_host = true, }, { .scheme = pb_url_sftp, .str = "sftp", .str_len = sizeof("sftp") - 1, + .has_host = true, }, { .scheme = pb_url_tftp, .str = "tftp", .str_len = sizeof("tftp") - 1, + .has_host = true, }, }; @@ -82,6 +91,21 @@ static const struct pb_scheme_info *file_scheme = &schemes[0]; * pb_url_find_scheme - Find the pb_scheme_info for a URL string. */ +static const struct pb_scheme_info *pb_url_scheme_info( + enum pb_url_scheme scheme) +{ + unsigned int i; + + for (i = 0; i < sizeof(schemes) / sizeof(schemes[0]); i++) { + const struct pb_scheme_info *info = &schemes[i]; + + if (info->scheme == scheme) + return info; + + } + return NULL; +} + static const struct pb_scheme_info *pb_url_find_scheme(const char *url) { static const int sep_len = sizeof("://") - 1; @@ -105,9 +129,24 @@ static const struct pb_scheme_info *pb_url_find_scheme(const char *url) return scheme; } - /* Assume this is a non-url local file. */ + return NULL; +} + +static void pb_url_parse_path(struct pb_url *url) +{ + const char *p = strrchr(url->path, '/'); + + talloc_free(url->dir); + talloc_free(url->file); - return file_scheme; + if (p) { + p++; + url->dir = talloc_strndup(url, url->path, p - url->path); + url->file = talloc_strdup(url, p); + } else { + url->dir = NULL; + url->file = talloc_strdup(url, url->path); + } } /** @@ -123,8 +162,6 @@ struct pb_url *pb_url_parse(void *ctx, const char *url_str) struct pb_url *url; const char *p; - pb_log("%s: '%s'\n", __func__, url_str); - if (!url_str || !*url_str) { assert(0 && "bad url"); return NULL; @@ -136,9 +173,13 @@ struct pb_url *pb_url_parse(void *ctx, const char *url_str) return NULL; si = pb_url_find_scheme(url_str); - - url->scheme = si->scheme; - p = url_str + si->str_len + strlen("://"); + if (si) { + url->scheme = si->scheme; + p = url_str + si->str_len + strlen("://"); + } else { + url->scheme = file_scheme->scheme; + p = url_str; + } url->full = talloc_strdup(url, url_str); @@ -178,23 +219,7 @@ struct pb_url *pb_url_parse(void *ctx, const char *url_str) url->path = talloc_strdup(url, path); } - p = strrchr(url->path, '/'); - - if (p) { - p++; - url->dir = talloc_strndup(url, url->path, p - url->path); - url->file = talloc_strdup(url, p); - } else { - url->dir = NULL; - url->file = talloc_strdup(url, url->path); - } - - pb_log(" scheme %d\n", url->scheme); - pb_log(" host '%s'\n", url->host); - pb_log(" port '%s'\n", url->port); - pb_log(" path '%s'\n", url->path); - pb_log(" dir '%s'\n", url->dir); - pb_log(" file '%s'\n", url->file); + pb_url_parse_path(url); return url; @@ -203,13 +228,77 @@ fail: return NULL; } -const char *pb_url_scheme_name(enum pb_url_scheme scheme) +static bool is_url(const char *str) { - unsigned int i; + return strstr(str, "://") != NULL; +} - for (i = 0; i < sizeof(schemes) / sizeof(schemes[0]); i++) - if (schemes[i].scheme == scheme) - return schemes[i].str; +char *pb_url_to_string(struct pb_url *url) +{ + const struct pb_scheme_info *scheme = pb_url_scheme_info(url->scheme); + assert(scheme); - return NULL; + return talloc_asprintf(url, "%s://%s%s", scheme->str, + scheme->has_host ? url->host : "", url->path); +} + +static void pb_url_update_full(struct pb_url *url) +{ + talloc_free(url->full); + url->full = pb_url_to_string(url); +} + +static struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url) +{ + struct pb_url *new_url; + + new_url = talloc(ctx, struct pb_url); + new_url->scheme = url->scheme; + new_url->full = talloc_strdup(new_url, url->full); + + new_url->host = url->host ? talloc_strdup(new_url, url->host) : NULL; + new_url->port = url->port ? talloc_strdup(new_url, url->port) : NULL; + new_url->path = url->path ? talloc_strdup(new_url, url->path) : NULL; + new_url->dir = url->dir ? talloc_strdup(new_url, url->dir) : NULL; + new_url->file = url->file ? talloc_strdup(new_url, url->file) : NULL; + + return new_url; +} + +struct pb_url *pb_url_join(void *ctx, const struct pb_url *url, const char *s) +{ + struct pb_url *new_url; + + /* complete url: just parse all info from s */ + if (is_url(s)) + return pb_url_parse(ctx, s); + + new_url = pb_url_copy(ctx, url); + + if (s[0] == '/') { + /* absolute path: replace path of new_url */ + talloc_free(new_url->path); + new_url->path = talloc_strdup(new_url, s); + + } else { + /* relative path: join s to existing path. We know that + * url->dir ends with a slash. */ + char *tmp = new_url->path; + new_url->path = talloc_asprintf(new_url, "%s%s", url->dir, s); + talloc_free(tmp); + } + + /* replace ->dir and ->file with components from ->path */ + pb_url_parse_path(new_url); + + /* and re-generate the full URL */ + pb_url_update_full(new_url); + + return new_url; +} + +const char *pb_url_scheme_name(enum pb_url_scheme scheme) +{ + const struct pb_scheme_info *info = pb_url_scheme_info(scheme); + return info ? info->str : NULL; }