Re: [RFC PATCH] configure: check for POSIX.1-2008 realpath(3) implementation.

Subject: Re: [RFC PATCH] configure: check for POSIX.1-2008 realpath(3) implementation.

Date: Sun, 26 Jan 2014 00:22:47 +0200

To: notmuch@notmuchmail.org

Cc:

From: Tomi Ollila


On Sat, Jan 25 2014, Tomi Ollila <tomi.ollila@iki.fi> wrote:

> Check whether realpath(3) supports the resolved_path == NULL feature,
> standardized in POSIX.1-2008.
>
> This is tested by executing the realpath(3) with NULL as second
> argument and the program is expected to SIGSEGV in case the
> feature is not supported.
>
> If the feature is not supported the compatibility code calls realpath(3)
> with second argument pointing to buffer with MAX_PATH in size. With
> this more systems are supported; those that have POSIX.1-2008 -capable
> realpath(3) and those that have MAX_PATH defined and realpath(3) does
> not exceed that limit.
> ---
>
> I tested running configure and then make test; then make clean,
> edited Makefile.config POSIX_2008_REALPATH = 0 and make clean
> again. then tested sigsegv'ing with (memcpy(0, 0, 4)...
>
>
>  configure        | 32 ++++++++++++++++++++++++++++++--
>  notmuch-config.c | 21 ++++++++++++++++++++-
>  2 files changed, 50 insertions(+), 3 deletions(-)
>
> diff --git a/configure b/configure
> index 13b6062..8174219 100755
> --- a/configure
> +++ b/configure
> @@ -454,6 +454,29 @@ echo $util_byte_order
>  
>  rm -f _byteorder _byteorder.c
>  
> +printf "Checking for posix 2008 realpath()... "
> +# resolved_path == NULL is standardized in POSIX.1-2008
> +cat > _posix_2008_realpath.c <<EOF
> +#define _BSD_SOURCE
> +#include <limits.h>
> +#include <stdlib.h>
> +#include <signal.h>
> +void exit1(int sig) { exit(1); }
> +int main () {
> + signal(SIGSEGV, exit1);
> + int main () { realpath (".", (char*)0); return 0;
> +}
> +EOF
> +${CC} ${CFLAGS} _posix_2008_realpath.c -o _posix_2008_realpath > /dev/null 2>&1
> +if ./_posix_2008_realpath; then
> +	echo Yes.
> +	posix_2008_realpath=1
> +else
> +	echo No.
> +	posix_2008_realpath=0
> +fi
> +rm -f _posix_2008_realpath _posix_2008_realpath.c
> +
>  if [ $errors -gt 0 ]; then
>      cat <<EOF
>  
> @@ -718,6 +741,9 @@ libdir = ${LIBDIR:=\$(prefix)/lib}
>  # byte order within a 32 bit word. 1234 = little, 4321 = big, 0 = guess
>  UTIL_BYTE_ORDER = ${util_byte_order}
>  
> +# Whether realpath(3) supports resolved_path == NULL feature
> +POSIX_2008_REALPATH = ${posix_2008_realpath}
> +
>  # Whether libdir is in a path configured into ldconfig
>  LIBDIR_IN_LDCONFIG = ${libdir_in_ldconfig}
>  
> @@ -824,7 +850,8 @@ CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)      \\
>  		   -DSTD_GETPWUID=\$(STD_GETPWUID)                       \\
>  		   -DSTD_ASCTIME=\$(STD_ASCTIME)                         \\
>  		   -DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT)	 \\
> -		   -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)
> +		   -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)		 \\
> +		   -DPOSIX_2008_REALPATH=\$(POSIX_2008_REALPATH)
>  
>  CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\
>  		     \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\
> @@ -834,7 +861,8 @@ CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\
>  		     -DSTD_GETPWUID=\$(STD_GETPWUID)                     \\
>  		     -DSTD_ASCTIME=\$(STD_ASCTIME)                       \\
>  		     -DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT)       \\
> -		     -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)
> +		     -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)		 \\
> +		     -DPOSIX_2008_REALPATH=\$(POSIX_2008_REALPATH)
>  
>  CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS)
>  EOF
> diff --git a/notmuch-config.c b/notmuch-config.c
> index 8d28653..14d0e5c 100644
> --- a/notmuch-config.c
> +++ b/notmuch-config.c
> @@ -454,10 +454,26 @@ notmuch_config_save (notmuch_config_t *config)
>      }
>  
>      /* Try not to overwrite symlinks. */
> +#if POSIX_2008_REALPATH
>      filename = realpath (config->filename, NULL);
> +#else
> +    /* compatibility with minor effort, not elegance, is the ruling factor
> +       in these (two) else branches... */
> +    char resolved_path[PATH_MAX];
> +    filename = realpath (config->filename, resolved_path);
> +#endif
>      if (! filename) {
>  	if (errno == ENOENT) {
> +#if POSIX_2008_REALPATH
>  	    filename = strdup (config->filename);
> +#else
> +	    /* ... this is the other else... */
> +	    resolved_path[sizeof resolved_path - 1] = '\0';
> +	    strncpy(resolved_path, config->filename, sizeof resolved_path);
> +	    /* "faking" out of memory in case path too long -- close enough? */
> +	    filename = resolved_path[sizeof resolved_path - 1]?
> +		resolved_path: NULL;

Ok, this above is wrong (should be other way around). Tests pass though
meaning this is not within test coverage...

Tomi

> +#endif
>  	    if (! filename) {
>  		fprintf (stderr, "Out of memory.\n");
>  		g_free (data);
> @@ -480,12 +496,15 @@ notmuch_config_save (notmuch_config_t *config)
>  		     filename, error->message);
>  	}
>  	g_error_free (error);
> +#if POSIX_2008_REALPATH
>  	free (filename);
> +#endif
>  	g_free (data);
>  	return 1;
>      }
> -
> +#if POSIX_2008_REALPATH
>      free (filename);
> +#endif
>      g_free (data);
>      return 0;
>  }
> -- 
> 1.8.5.3

Thread: