From 425d2ad2ee8013d9bbc65d5727dae27bb323857a Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Tue, 12 Jul 2022 19:08:46 +0000 Subject: [PATCH] lib/cmd/bup.c: Accomodate historical realpath realpath(3) originally required a non-NULL 2nd argument. POSIX extended it to allow NULL, but some old BSD versions still have the as-first-introduced-in-4.4BSD implementation that does not accept the 2nd argument being NULL. Define bup_realpath, which collapses to just system realpath for most systems, and on systems known to have historic realpath, use a buffer, and strdup the results, to match the POSIX-with-NULL semantics. This should fix NetBSD and OpenBSD, and realpath isn't used on FreeBSD. This does not attempt to address Solaris. Signed-off-by: Greg Troxel Reviewed-by: Rob Browning [rlb@defaultvalue.org: adjust commit message] [rlb@defaultvalue.org: change #define to BUP_HAVE_POSIX_REALPATH] [rlb@defaultvalue.org: add OpenBSD version guard clause] [rlb@defaultvalue.org: nest NetBSD checks so Prereq doesn't crash elsewhere] [rlb@defaultvalue.org: reformat bup_realpath a bit] Signed-off-by: Rob Browning Tested-by: Rob Browning --- lib/cmd/bup.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/lib/cmd/bup.c b/lib/cmd/bup.c index 9cd1f38..0d002a9 100644 --- a/lib/cmd/bup.c +++ b/lib/cmd/bup.c @@ -96,6 +96,46 @@ setup_bup_main_module(void) { die(2, "unable to register bup_main module\n"); } +/* + * Older realpath implementations (e.g. 4.4BSD) required the second + * argument to be non-NULL, and then POSIX added the option of NULL + * with the semantics of malloc'ing a big-enough buffer. Define a + * helper function with the NULL semantics to accomodate older + * platforms. + * + * gnulib has a list of systems that are known to reject NULL as the + * 2nd argument: + * https://www.gnu.org/software/gnulib/manual/html_node/realpath.html + */ + +#define BUP_HAVE_POSIX_REALPATH + +// FreeBSD < 7: bup's FreeBSD code does not use realpath(3) +#if defined(__NetBSD__) +# if !__NetBSD_Prereq__(7,0,0) +# undef BUP_HAVE_POSIX_REALPATH +# endif +// OpenBSD: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/param.h.diff?r1=1.91&r2=1.92&f=h +#elif defined(__OpenBSD__) && __OpenBSD__ < 201111 +# undef BUP_HAVE_POSIX_REALPATH +#endif + +char * +bup_realpath(const char *pathname) +{ +#ifdef BUP_HAVE_POSIX_REALPATH + return realpath(pathname, NULL); +#else + char resolvedname[PATH_MAX]; + char *ret = realpath(pathname, resolvedname); + if (ret != NULL) { + assert(ret == resolvedname); + ret = strdup(ret); + } + return ret; +#endif +} + #if defined(__APPLE__) && defined(__MACH__) static char *exe_parent_dir(const char * const argv_0) { @@ -110,7 +150,7 @@ static char *exe_parent_dir(const char * const argv_0) { } if(rc != 0) die(2, "unable to find executable path\n"); char *path = mpath ? mpath : spath; - char *abs_exe = realpath(path, NULL); + char *abs_exe = bup_realpath(path); if (!abs_exe) die(2, "cannot resolve path (%s): %s\n", strerror(errno), path); char * const abs_parent = strdup(dirname(abs_exe)); @@ -215,7 +255,7 @@ static char *find_exe_parent(const char * const argv_0) argv_0); char *path_exe = find_in_path(argv_0, env_path); if (path_exe) { - char * abs_exe = realpath(path_exe, NULL); + char * abs_exe = bup_realpath(path_exe); if (!abs_exe) die(2, "cannot resolve path (%s): %s\n", strerror(errno), path_exe); @@ -226,7 +266,7 @@ static char *find_exe_parent(const char * const argv_0) if (!candidate) return NULL; - char * const abs_exe = realpath(candidate, NULL); + char * const abs_exe = bup_realpath(candidate); if (!abs_exe) die(2, "cannot resolve path (%s): %s\n", strerror(errno), candidate); free(candidate); -- 2.39.2