This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=2ef72befaa2ff1a93cc9e90d202f54ecefeafcad commit 2ef72befaa2ff1a93cc9e90d202f54ecefeafcad Author: Guillem Jover <[email protected]> AuthorDate: Wed May 15 20:17:54 2024 +0200 libdpkg: Add new file_canonicalize() function Try to canonicalize a pathname based on what is on the filesystem. If the pathname does not exist, then try a lexical canonicalization. --- lib/dpkg/file.c | 24 ++++++++++++++++++++++++ lib/dpkg/file.h | 3 +++ lib/dpkg/t/t-file.c | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/dpkg/file.c b/lib/dpkg/file.c index 8415572d5..4251e9cba 100644 --- a/lib/dpkg/file.c +++ b/lib/dpkg/file.c @@ -35,6 +35,7 @@ #include <dpkg/pager.h> #include <dpkg/fdio.h> #include <dpkg/buffer.h> +#include <dpkg/path.h> #include <dpkg/file.h> #include <dpkg/execname.h> @@ -91,6 +92,29 @@ file_realpath(const char *pathname) return resolved_path; } +/** + * Canonicalize a pathname (physically or lexically). + * + * Try to canonicalize a pathname based on what is on the filesystem. If + * the pathname does not exist, then try a lexical canonicalization. + * + * @param pathname The pathname to canonicalize. + * + * @return The allocated canonicalized pathname. + */ +char * +file_canonicalize(const char *pathname) +{ + char *canon_path; + + errno = 0; + canon_path = file_realpath(pathname); + if (canon_path == NULL) + canon_path = path_canonicalize(pathname); + + return canon_path; +} + /** * Read the symlink content into a varbuf. * diff --git a/lib/dpkg/file.h b/lib/dpkg/file.h index 7f7b8530f..a0425f182 100644 --- a/lib/dpkg/file.h +++ b/lib/dpkg/file.h @@ -54,6 +54,9 @@ file_getcwd(struct varbuf *cwd); char * file_realpath(const char *pathname); +char * +file_canonicalize(const char *pathname); + ssize_t file_readlink(const char *slink, struct varbuf *content, size_t content_len); diff --git a/lib/dpkg/t/t-file.c b/lib/dpkg/t/t-file.c index ccaecbb7a..0f8e41709 100644 --- a/lib/dpkg/t/t-file.c +++ b/lib/dpkg/t/t-file.c @@ -71,6 +71,42 @@ test_file_realpath(void) free(path); } +static void +test_file_canonicalize(void) +{ + char *path; + + /* Canonicalize filenames that exist. */ + path = file_canonicalize("/"); + test_str(path, ==, "/"); + free(path); + + path = file_canonicalize("///"); + test_str(path, ==, "/"); + free(path); + + path = file_canonicalize("//./..///../././..///.."); + test_str(path, ==, "/"); + free(path); + + /* Canonicalize filenames that do not exist. */ + path = file_canonicalize("/./nonexistent/..///./bar///../././../..///end//."); + test_str(path, ==, "/end"); + free(path); + + path = file_canonicalize("foo/../bar/../quux////fox"); + test_str(path, ==, "quux/fox"); + free(path); + + path = file_canonicalize(".//aa/../bb///cc/./../dd//"); + test_str(path, ==, "bb/dd"); + free(path); + + path = file_canonicalize("..////../aa/../..///bb/../../cc/dd//"); + test_str(path, ==, "cc/dd"); + free(path); +} + static void test_file_slurp(void) { @@ -132,9 +168,10 @@ test_file_slurp(void) TEST_ENTRY(test) { - test_plan(36); + test_plan(43); test_file_getcwd(); test_file_realpath(); + test_file_canonicalize(); test_file_slurp(); } -- Dpkg.Org's dpkg

