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=a47530f1649b81d9feb85fefff1e96ee468bd768 commit a47530f1649b81d9feb85fefff1e96ee468bd768 Author: Guillem Jover <[email protected]> AuthorDate: Sat Apr 20 02:06:05 2024 +0200 libdpkg: Add new file_realpath() function This function wraps the system realpath(3) function and handles whether it supports the POSIX.1-2008 semantics where passing a NULL argument for the resolved pathname makes the function allocate the necessary memory. We key this legacy fallback on whether PATH_MAX is defined, as the systems that might not have the required semantics do define that macro, even if POSIX specifies that defining it is optional. --- lib/dpkg/file.c | 40 ++++++++++++++++++++++++++++++++++++++++ lib/dpkg/file.h | 3 +++ lib/dpkg/libdpkg.map | 1 + lib/dpkg/t/t-file.c | 21 ++++++++++++++++++++- 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/lib/dpkg/file.c b/lib/dpkg/file.c index f664feb94..8415572d5 100644 --- a/lib/dpkg/file.c +++ b/lib/dpkg/file.c @@ -27,6 +27,7 @@ #include <errno.h> #include <fcntl.h> +#include <stdlib.h> #include <unistd.h> #include <dpkg/dpkg.h> @@ -51,6 +52,45 @@ file_getcwd(struct varbuf *cwd) varbuf_trunc(cwd, strlen(cwd->buf)); } +/* + * Handle pre-POSIX-1.2008 realpath() semantics, by using a fixed size buffer + * based on PATH_MAX, which we expect to be defined on the systems that have + * no proper behavior for this function. + */ +#ifdef PATH_MAX +static char * +file_realpath_legacy(const char *pathname) +{ + char resolved_path_buf[PATH_MAX]; + char *resolved_path; + + resolved_path = realpath(pathname, resolved_path_buf); + if (resolved_path == NULL && errno != ENOENT) + ohshite(_("cannot canonicalize pathname %s"), pathname); + + if (resolved_path) + return m_strdup(resolved_path); + return NULL; +} +#endif + +char * +file_realpath(const char *pathname) +{ + char *resolved_path; + + resolved_path = realpath(pathname, NULL); + if (resolved_path == NULL && errno != ENOENT) { +#ifdef PATH_MAX + if (errno == EINVAL) + return file_realpath_legacy(pathname); +#endif + ohshite(_("cannot canonicalize pathname %s"), pathname); + } + + return resolved_path; +} + /** * Read the symlink content into a varbuf. * diff --git a/lib/dpkg/file.h b/lib/dpkg/file.h index f5bc50d1a..7f7b8530f 100644 --- a/lib/dpkg/file.h +++ b/lib/dpkg/file.h @@ -51,6 +51,9 @@ struct file_stat { void file_getcwd(struct varbuf *cwd); +char * +file_realpath(const char *pathname); + ssize_t file_readlink(const char *slink, struct varbuf *content, size_t content_len); diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map index 6185377ed..8e0b9c0ab 100644 --- a/lib/dpkg/libdpkg.map +++ b/lib/dpkg/libdpkg.map @@ -174,6 +174,7 @@ LIBDPKG_PRIVATE { treewalk; file_getcwd; + file_realpath; file_readlink; file_is_exec; file_copy_perms; diff --git a/lib/dpkg/t/t-file.c b/lib/dpkg/t/t-file.c index 16114f061..ccaecbb7a 100644 --- a/lib/dpkg/t/t-file.c +++ b/lib/dpkg/t/t-file.c @@ -53,6 +53,24 @@ test_file_getcwd(void) varbuf_destroy(&cwd); } +static void +test_file_realpath(void) +{ + char *path; + + path = file_realpath("/"); + test_str(path, ==, "/"); + free(path); + + path = file_realpath("///"); + test_str(path, ==, "/"); + free(path); + + path = file_realpath("//./..///../././..///.."); + test_str(path, ==, "/"); + free(path); +} + static void test_file_slurp(void) { @@ -114,8 +132,9 @@ test_file_slurp(void) TEST_ENTRY(test) { - test_plan(33); + test_plan(36); test_file_getcwd(); + test_file_realpath(); test_file_slurp(); } -- Dpkg.Org's dpkg

