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

Reply via email to