Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 49 additions & 5 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -448,20 +448,64 @@ AC_MSG_RESULT($HIDRAW_H_USABLE)
AC_SUBST([HIDRAW_H_USABLE])

#
# Check for rpc/rpc.h
# Check the system XDR routines used by NML
#

AC_MSG_CHECKING([for usability of rpc/rpc.h])
# Detect names for which the compatibility header provides replacements.
# Signed 16/32/64-bit primitives remain required and are link-tested below.
AC_CHECK_DECLS([xdr_int8_t, xdr_uint8_t, xdr_uint16_t, xdr_uint32_t, xdr_uint64_t],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an assumption that xdr_int16_t, xdr_int32_t and xdr_int64_t exist unconditionally, while the unsigned versions is tested for. But not for the 8-bit version.
What are the guarantees that, for example, xdr_int64_t exists. The 64-bit version is also likely to be missing with old lib versions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I am not with you. There is no assumption that every RPC library provides these functions. AC_CHECK_DECLS selects the available adaptations; the following AC_LINK_IFELSE requires the signed 16-, 32- and 64-bit routines. An older library missing one will fail configure. NML already uses these routines unconditionally. Will add a respective comment.

[], [], [[#include <rpc/rpc.h>]])

AC_MSG_CHECKING([for usable fixed-width RPC/XDR routines])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <rpc/rpc.h>
#include <stdint.h>
]], [[
struct sockaddr_in *foo;
get_myaddress(foo);
/* Probe the fixed-width and memory-stream subset used by cms_xup.cc.
Parenthesized calls fail for undeclared functions even where older
C compilers would implicitly declare a plain call. xdr_getpos,
xdr_setpos and xdr_destroy are macros and stay unparenthesized. */
XDR xdrs;
char buf[64] = {0};
int16_t i16 = 0; uint16_t u16 = 0;
int32_t i32 = 0; uint32_t u32 = 0; int64_t i64 = 0; uint64_t u64 = 0;
(xdrmem_create)(&xdrs, buf, sizeof buf, XDR_ENCODE);
/* Missing 8-bit names use the 32-bit primitives checked below. */
#if HAVE_DECL_XDR_INT8_T
int8_t i8 = 0;
(xdr_int8_t)(&xdrs, &i8);
#endif
#if HAVE_DECL_XDR_UINT8_T
uint8_t u8 = 0;
(xdr_uint8_t)(&xdrs, &u8);
#endif
(xdr_int16_t)(&xdrs, &i16);
#if HAVE_DECL_XDR_UINT16_T
(xdr_uint16_t)(&xdrs, &u16);
#else
(xdr_u_int16_t)(&xdrs, &u16);
#endif
(xdr_int32_t)(&xdrs, &i32);
#if HAVE_DECL_XDR_UINT32_T
(xdr_uint32_t)(&xdrs, &u32);
#endif
/* The unsigned 8-bit adapter also needs xdr_u_int32_t. */
#if !HAVE_DECL_XDR_UINT8_T || !HAVE_DECL_XDR_UINT32_T
(xdr_u_int32_t)(&xdrs, &u32);
#endif
(xdr_int64_t)(&xdrs, &i64);
#if HAVE_DECL_XDR_UINT64_T
(xdr_uint64_t)(&xdrs, &u64);
#else
(xdr_u_int64_t)(&xdrs, &u64);
#endif
xdr_setpos(&xdrs, xdr_getpos(&xdrs));
xdr_destroy(&xdrs);
]])],[
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([Unable to use rpc.h])
AC_MSG_ERROR([Required fixed-width RPC/XDR routines unavailable; see config.log for missing declarations or symbols])

])

Expand Down
2 changes: 2 additions & 0 deletions src/libnml/cms/cms_xup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* Last change:
********************************************************************/

#include "nml_xdr_compat.h"

#include <stdlib.h> /* malloc(), free() */

#include <vector>
Expand Down
75 changes: 75 additions & 0 deletions src/libnml/cms/nml_xdr_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* Fixed-width XDR names used by cms_xup.cc but missing from some system
RPC/XDR implementations. Prefer declared native routines; fill only gaps.
HAVE_DECL_* come from the included config.h.

License: LGPL Version 2 or later */
#ifndef LIBNML_CMS_NML_XDR_COMPAT_H
#define LIBNML_CMS_NML_XDR_COMPAT_H

#include "config.h"
#include <rpc/rpc.h>
#include <stdint.h>

/* An undefined HAVE_DECL_* would read as 0 below and mask a native routine. */
#if !defined(HAVE_DECL_XDR_INT8_T) || !defined(HAVE_DECL_XDR_UINT8_T) || \
!defined(HAVE_DECL_XDR_UINT16_T) || !defined(HAVE_DECL_XDR_UINT32_T) || \
!defined(HAVE_DECL_XDR_UINT64_T)
#error "XDR declaration results are missing (HAVE_DECL_XDR_*)"
#endif

/* Alternate unsigned names with the same 4/8-byte XDR encodings. */
#if !HAVE_DECL_XDR_UINT16_T
#define xdr_uint16_t xdr_u_int16_t
#endif
#if !HAVE_DECL_XDR_UINT32_T
#define xdr_uint32_t xdr_u_int32_t
#endif
#if !HAVE_DECL_XDR_UINT64_T
#define xdr_uint64_t xdr_u_int64_t
#endif

/* One 32-bit XDR word; decode narrows without range checks, as in
glibc/libtirpc. Failed decodes leave *p unchanged. */
#if !HAVE_DECL_XDR_INT8_T
static inline bool_t nml_xdr_int8_t(XDR *xdrs, int8_t *p)
{
int32_t t;
switch (xdrs->x_op) {
case XDR_ENCODE:
t = *p;
return (xdr_int32_t)(xdrs, &t);
case XDR_DECODE:
if (!(xdr_int32_t)(xdrs, &t))
return FALSE;
*p = (int8_t) t;
return TRUE;
case XDR_FREE:
return TRUE;
}
return FALSE;
}
#define xdr_int8_t nml_xdr_int8_t
#endif

#if !HAVE_DECL_XDR_UINT8_T
static inline bool_t nml_xdr_uint8_t(XDR *xdrs, uint8_t *p)
{
uint32_t t;
switch (xdrs->x_op) {
case XDR_ENCODE:
t = *p;
return (xdr_u_int32_t)(xdrs, &t);
case XDR_DECODE:
if (!(xdr_u_int32_t)(xdrs, &t))
return FALSE;
*p = (uint8_t) t;
return TRUE;
case XDR_FREE:
return TRUE;
}
return FALSE;
}
#define xdr_uint8_t nml_xdr_uint8_t
#endif

#endif
Loading