diff options
author | David Robillard <d@drobilla.net> | 2020-11-10 09:45:15 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-03-08 23:23:06 -0500 |
commit | 8f1192bb2361fcd7907b926e86c41a171ed04ad0 (patch) | |
tree | fdaeb65c1210c09128b890cd452b7940644e49a4 | |
parent | 79367b620492ac941f41c61adbffc29867ac0998 (diff) | |
download | serd-8f1192bb2361fcd7907b926e86c41a171ed04ad0.tar.gz serd-8f1192bb2361fcd7907b926e86c41a171ed04ad0.tar.bz2 serd-8f1192bb2361fcd7907b926e86c41a171ed04ad0.zip |
Add serd_new_real_file_uri()
-rw-r--r-- | include/serd/serd.h | 16 | ||||
-rw-r--r-- | src/node.c | 47 | ||||
-rw-r--r-- | test/.clang-tidy | 4 | ||||
-rw-r--r-- | test/test_uri.c | 26 |
4 files changed, 92 insertions, 1 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h index a2e767ff..dd165360 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -674,6 +674,22 @@ SerdNode* SERD_ALLOCATED serd_new_boolean(bool b); /** + Create a new file URI node for a file that exists on this system. + + This is like serd_new_file_uri() except it resolves and canonicalizes the + path, so the returned node is always a complete file URI with a scheme and + absolute path that does not contain any dot references or links, or NULL if + this is impossible (for example, because the path does not exist). + + This should be used wherever the URI for an existent file is required, for + example to set the base URI of a document. +*/ +SERD_API +SerdNode* SERD_ALLOCATED +serd_new_real_file_uri(const char* SERD_NULLABLE path, + const char* SERD_NULLABLE hostname); + +/** Create a new node by serialising `d` into an xsd:decimal string The resulting node will always contain a `.', start with a digit, and end @@ -14,6 +14,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define _XOPEN_SOURCE 600 /* for realpath */ + #include "node.h" #include "namespaces.h" @@ -24,6 +26,11 @@ #include "exess/exess.h" #include "serd/serd.h" +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +#endif + #include <assert.h> #include <float.h> #include <math.h> @@ -539,6 +546,32 @@ is_uri_path_char(const char c) } } +static char* +serd_realpath(const char* const path) +{ + if (!path) { + return NULL; + } + +#ifdef _WIN32 + const DWORD size = GetFullPathName(path, 0, NULL, NULL); + if (size == 0) { + return NULL; + } + + char* const out = (char*)calloc(size, 1); + const DWORD ret = GetFullPathName(path, MAX_PATH, out, NULL); + if (ret == 0 || ret >= size) { + free(out); + return NULL; + } + + return out; +#else + return realpath(path, NULL); +#endif +} + SerdNode* serd_new_file_uri(const SerdStringView path, const SerdStringView hostname) { @@ -586,6 +619,20 @@ serd_new_file_uri(const SerdStringView path, const SerdStringView hostname) return node; } +SerdNode* +serd_new_real_file_uri(const char* const path, const char* const hostname) +{ + char* const real_path = serd_realpath(path); + if (!real_path) { + return NULL; + } + + SerdNode* const node = serd_new_file_uri(SERD_MEASURE_STRING(real_path), + SERD_MEASURE_STRING(hostname)); + free(real_path); + return node; +} + typedef size_t (*SerdWriteLiteralFunc)(const void* const user_data, const size_t buf_size, char* const buf); diff --git a/test/.clang-tidy b/test/.clang-tidy index de654d8d..b7dd752b 100644 --- a/test/.clang-tidy +++ b/test/.clang-tidy @@ -3,6 +3,10 @@ Checks: > -*-magic-numbers, -*-uppercase-literal-suffix, -android-cloexec-fopen, + -bugprone-reserved-identifier, + -bugprone-suspicious-string-compare, + -cert-dcl37-c, + -cert-dcl51-cpp, -clang-analyzer-nullability.NullabilityBase, -clang-analyzer-nullability.NullableDereferenced, -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, diff --git a/test/test_uri.c b/test/test_uri.c index 88aa342c..dff4d999 100644 --- a/test/test_uri.c +++ b/test/test_uri.c @@ -20,6 +20,11 @@ #include "serd/serd.h" +#if defined(_WIN32) && !defined(__MINGW32__) +# include <io.h> +# define mkstemp(pat) _mktemp(pat) +#endif + #include <assert.h> #include <stdio.h> #include <stdlib.h> @@ -80,6 +85,24 @@ test_uri_parsing(void) } static void +test_real_file_uri(void) +{ + char path[16]; + strncpy(path, "serd_XXXXXX", sizeof(path)); + assert(mkstemp(path) > 0); + + SerdNode* const good = serd_new_real_file_uri(path, NULL); + assert(good); + assert(!strncmp(serd_node_string(good), "file://", 7)); + serd_node_free(good); + + SerdNode* const bad = serd_new_real_file_uri("not_a_file", NULL); + assert(!bad); + + assert(!remove(path)); +} + +static void test_parse_uri(void) { const SerdStringView base = SERD_STATIC_STRING("http://example.org/a/b/c/"); @@ -204,7 +227,7 @@ test_uri_resolution(void) const SerdURIView rel_foo_uri = serd_relative_uri(abs_foo_uri, base_uri); const SerdURIView resolved_uri = serd_resolve_uri(rel_foo_uri, base_uri); -SerdNode* const resolved = serd_new_parsed_uri(resolved_uri); + SerdNode* const resolved = serd_new_parsed_uri(resolved_uri); assert(!strcmp(serd_node_string(resolved), "http://example.org/a/b/c/foo")); serd_node_free(resolved); @@ -215,6 +238,7 @@ main(void) { test_uri_parsing(); test_parse_uri(); + test_real_file_uri(); test_is_within(); test_relative_uri(); test_uri_resolution(); |