From: Juergen Perlinger Date: Sat, 26 Nov 2016 17:10:01 +0000 (+0100) Subject: [Bug 3139] (...) time_pps_create: Exec format error X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7994361c7f54fa7797663957e4284414b0880abc;p=thirdparty%2Fntp.git [Bug 3139] (...) time_pps_create: Exec format error bk: 5839c1e9jXvLURh6P2QoYj0Q_1DO5g --- diff --git a/ChangeLog b/ChangeLog index 0cb8c4fb4..cb70a443f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +--- +* [Bug 3139] (...) time_pps_create: Exec format error + - move loader API from 'inline' to proper source + - augment pathless dlls with absolute path to NTPD + - use 'msyslog()' instead of 'printf() 'for reporting trouble + --- (4.2.8p9) 2016/11/21 Released by Harlan Stenn (4.2.8p9) 2016/MM/DD Released by Harlan Stenn diff --git a/ports/winnt/include/timepps.h b/ports/winnt/include/timepps.h index 76b1bfada..b39951c3f 100644 --- a/ports/winnt/include/timepps.h +++ b/ports/winnt/include/timepps.h @@ -223,8 +223,6 @@ typedef struct pps_params { #include #include -#include /* offsetof() */ -#include /* _get_osfhandle() */ #ifndef EOPNOTSUPP #define EOPNOTSUPP 45 @@ -232,10 +230,6 @@ typedef struct pps_params { typedef UINT_PTR pps_handle_t; /* pps handlebars */ -#ifndef inline -#define inline __inline -#endif - /* * ntpd on Windows is typically distributed as a binary as few users * have the tools needed to build from source. Rather than build @@ -327,61 +321,6 @@ typedef struct pps_provider_tag { provtime_pps_kcbind ptime_pps_kcbind; } ppsapi_provider; -static ppsapi_provider * g_provider_list; -static ppsapi_provider * g_curr_provider; - - -static inline pps_handle_t -internal_create_pps_handle( - void * prov_context - ) -{ - pps_unit_t * punit; - - if (NULL == g_curr_provider) { - fprintf(stderr, "create_pps_handle: provider backend called me outside time_pps_create\n"); - punit = NULL; - } else - punit = malloc(sizeof(*punit)); - if (punit != NULL) { - punit->provider = g_curr_provider; - punit->context = prov_context; - punit->magic = PPSAPI_MAGIC_UNIT; - memset(&punit->params, 0, sizeof(punit->params)); - } - return (pps_handle_t)punit; -} - -static inline pps_unit_t * -unit_from_ppsapi_handle( - pps_handle_t handle - ) -{ - pps_unit_t *punit; - - punit = (pps_unit_t *)handle; - if (PPSAPI_MAGIC_UNIT != punit->magic) - punit = NULL; - return punit; -} - -/* - * ntpd on Windows only looks to errno after finding - * GetLastError returns NO_ERROR. To accomodate its - * use of msyslog in portable code such as refclock_atom.c, - * this implementation always clears the Windows - * error code using SetLastError(NO_ERROR) when - * returning an errno. This is also a good idea - * for any non-ntpd clients as they should rely only - * the errno for PPSAPI functions. - */ -#define RETURN_PPS_ERRNO(e) \ -do { \ - SetLastError(NO_ERROR); \ - errno = (e); \ - return -1; \ -} while (0) - #ifdef OWN_PPS_NTP_TIMESTAMP_FROM_COUNTER extern void pps_ntp_timestamp_from_counter(ntp_fp_t *, ULONGLONG, ULONGLONG); @@ -422,98 +361,6 @@ pps_ntp_timestamp_from_counter( #endif -static inline int -load_pps_provider( - char * dllpath - ) -{ - char short_name[16]; - char full_name[64]; - ppsapi_provider * prov; - HMODULE hmod; - pppsapi_prov_init pprov_init; - - prov = malloc(sizeof(*prov)); - if (NULL == prov) - return ENOMEM; - - hmod = LoadLibrary(dllpath); - if (NULL == hmod) { - fprintf(stderr, "load_pps_provider: LoadLibrary(%s) error %u\n", dllpath, GetLastError()); - free(prov); - return ENOENT; - } - - pprov_init = (pppsapi_prov_init)GetProcAddress(hmod, "ppsapi_prov_init"); - if (NULL == pprov_init) { - fprintf(stderr, "load_pps_provider: entrypoint ppsapi_prov_init not found in %s\n", dllpath); - free(prov); - FreeLibrary(hmod); - return EFAULT; - } - - prov->caps = (*pprov_init)(PPSAPI_TIMEPPS_PROV_VER, - &internal_create_pps_handle, - &pps_ntp_timestamp_from_counter, - short_name, sizeof(short_name), - full_name, sizeof(full_name)); - - if (!prov->caps) { - free(prov); - FreeLibrary(hmod); - return EACCES; - } - - prov->short_name = _strdup(short_name); - prov->full_name = _strdup(full_name); - - if (NULL == prov->short_name || !prov->short_name[0] - || NULL == prov->full_name || !prov->full_name[0]) { - - if (prov->short_name) - free(prov->short_name); - if (prov->full_name) - free(prov->full_name); - free(prov); - FreeLibrary(hmod); - return EINVAL; - } - - prov->ptime_pps_create = (provtime_pps_create) - GetProcAddress(hmod, "prov_time_pps_create"); - prov->ptime_pps_destroy = (provtime_pps_destroy) - GetProcAddress(hmod, "prov_time_pps_destroy"); - prov->ptime_pps_setparams = (provtime_pps_setparams) - GetProcAddress(hmod, "prov_time_pps_setparams"); - prov->ptime_pps_fetch = (provtime_pps_fetch) - GetProcAddress(hmod, "prov_time_pps_fetch"); - prov->ptime_pps_kcbind = (provtime_pps_kcbind) - GetProcAddress(hmod, "prov_time_pps_kcbind"); - - if (NULL == prov->ptime_pps_create - || NULL == prov->ptime_pps_destroy - || NULL == prov->ptime_pps_setparams - || NULL == prov->ptime_pps_fetch - || NULL == prov->ptime_pps_kcbind) { - - fprintf(stderr, "PPSAPI provider %s missing entrypoint\n", - prov->short_name); - free(prov->short_name); - free(prov->full_name); - free(prov); - FreeLibrary(hmod); - return EINVAL; - } - - fprintf(stderr, "loaded PPSAPI provider %s caps 0x%x provider %p\n", - prov->full_name, prov->caps, prov); - - prov->next = g_provider_list; - g_provider_list = prov; - - return 0; -} - /* * time_pps_create - create PPS handle from file descriptor @@ -524,288 +371,69 @@ load_pps_provider( * descriptor namespace, though it may have been converted from a * native Windows HANDLE using _open_osfhandle(). */ -static inline int +extern int time_pps_create( int filedes,/* device file descriptor */ pps_handle_t * phandle /* returned handle */ - ) -{ - HANDLE winhandle; - char * dlls; - char * dll; - char * pch; - ppsapi_provider * prov; - pps_handle_t ppshandle; - int err; - - if (NULL == phandle) - RETURN_PPS_ERRNO(EFAULT); - - winhandle = (HANDLE)_get_osfhandle(filedes); - fprintf(stderr, "time_pps_create(%d) got winhandle %p\n", filedes, winhandle); - if (INVALID_HANDLE_VALUE == winhandle) - RETURN_PPS_ERRNO(EBADF); - - /* - * For initial testing the list of PPSAPI backend - * providers is provided by the environment variable - * PPSAPI_DLLS, separated by semicolons such as - * PPSAPI_DLLS=c:\ntp\serial_ppsapi.dll;..\parport_ppsapi.dll - * There are a million better ways, such as a well-known - * registry key under which a value is created for each - * provider DLL installed, or even a platform-specific - * ntp.conf directive or command-line switch. - */ - dlls = getenv("PPSAPI_DLLS"); - if (dlls != NULL && NULL == g_provider_list) { - dlls = dll = _strdup(dlls); - fprintf(stderr, "getenv(PPSAPI_DLLS) gives %s\n", dlls); - } else - dlls = dll = NULL; - - while (dll != NULL && dll[0]) { - pch = strchr(dll, ';'); - if (pch != NULL) - *pch = 0; - err = load_pps_provider(dll); - if (err) { - fprintf(stderr, "load_pps_provider(%s) got errno %d\n", dll, err); - RETURN_PPS_ERRNO(err); - } - dll = (NULL == pch) - ? NULL - : pch + 1; - } - - if (NULL != dlls) - free(dlls); - dlls = dll = NULL; - - /* - * Hand off to each provider in turn until one returns a PPS - * handle or they've all declined. - */ - for (prov = g_provider_list; prov != NULL; prov = prov->next) { - ppshandle = 0; - g_curr_provider = prov; - err = (*prov->ptime_pps_create)(winhandle, &ppshandle); - g_curr_provider = NULL; - fprintf(stderr, "%s prov_time_pps_create(%p) returned %d\n", - prov->short_name, winhandle, err); - if (!err && ppshandle) { - *phandle = ppshandle; - return 0; - } - } - - fprintf(stderr, "PPSAPI provider list %p\n", g_provider_list); - - RETURN_PPS_ERRNO(ENOEXEC); -} - + ); /* * release PPS handle */ - -static inline int +extern int time_pps_destroy( pps_handle_t handle - ) -{ - pps_unit_t * punit; - int err; - - if (!handle) - RETURN_PPS_ERRNO(EBADF); - - punit = unit_from_ppsapi_handle(handle); - - if (NULL == punit) - RETURN_PPS_ERRNO(EBADF); - - err = (*punit->provider->ptime_pps_destroy)(punit, punit->context); - - free(punit); - - if (err) - RETURN_PPS_ERRNO(err); - else - return 0; -} + ); /* * set parameters for handle */ - -static inline int +extern int time_pps_setparams( pps_handle_t handle, const pps_params_t *params - ) -{ - pps_unit_t * punit; - int err; - - /* - * Check for valid arguments and set parameters. - */ - if (!handle) - RETURN_PPS_ERRNO(EBADF); - - punit = unit_from_ppsapi_handle(handle); - - if (NULL == punit) - RETURN_PPS_ERRNO(EBADF); - - if (NULL == params) - RETURN_PPS_ERRNO(EFAULT); - - err = (*punit->provider->ptime_pps_setparams)(punit, punit->context, params); - - if (err) - RETURN_PPS_ERRNO(err); - else - return 0; -} + ); /* * get parameters for handle */ - -static inline int +extern int time_pps_getparams( pps_handle_t handle, pps_params_t *params_buf - ) -{ - pps_unit_t * punit; - - /* - * Check for valid arguments and get parameters. - */ - if (!handle) - RETURN_PPS_ERRNO(EBADF); - - punit = unit_from_ppsapi_handle(handle); - - if (NULL == punit) - RETURN_PPS_ERRNO(EBADF); - - if (NULL == params_buf) - RETURN_PPS_ERRNO(EFAULT); - - *params_buf = punit->params; - return 0; -} - + ); /* * time_pps_getcap - get capabilities for handle */ -static inline int +extern int time_pps_getcap( pps_handle_t handle, int *pmode - ) -{ - pps_unit_t * punit; - - /* - * Check for valid arguments and get capabilities. - */ - if (!handle) - RETURN_PPS_ERRNO(EBADF); - - punit = unit_from_ppsapi_handle(handle); - - if (NULL == punit) - RETURN_PPS_ERRNO(EBADF); - - if (NULL == pmode) - RETURN_PPS_ERRNO(EFAULT); - - *pmode = punit->provider->caps; - return 0; -} + ); /* * Fetch timestamps */ - -static inline int +extern int time_pps_fetch( pps_handle_t handle, const int tsformat, pps_info_t * pinfo, const struct timespec * ptimeout - ) -{ - pps_unit_t * punit; - int err; - - /* - * Check for valid arguments and fetch timestamps - */ - if (!handle) - RETURN_PPS_ERRNO(EBADF); - - if (NULL == pinfo) - RETURN_PPS_ERRNO(EFAULT); - - punit = unit_from_ppsapi_handle(handle); - - if (NULL == punit) - RETURN_PPS_ERRNO(EBADF); - - err = (*punit->provider->ptime_pps_fetch)(punit, - punit->context, - tsformat, - pinfo, - ptimeout); - - if (err) - RETURN_PPS_ERRNO(err); - else - return 0; -} + ); /* * time_pps_kcbind - specify kernel consumer * * Not supported so far by Windows. */ - -static inline int +extern int time_pps_kcbind( pps_handle_t handle, const int kernel_consumer, const int edge, const int tsformat - ) -{ - pps_unit_t * punit; - int err; - - if (!handle) - RETURN_PPS_ERRNO(EBADF); - - punit = unit_from_ppsapi_handle(handle); - - if (NULL == punit) - RETURN_PPS_ERRNO(EBADF); - - err = (*punit->provider->ptime_pps_kcbind)( - punit, - punit->context, - kernel_consumer, - edge, - tsformat); - - if (err) - RETURN_PPS_ERRNO(err); - else - return 0; -} + ); #endif /* TIMEPPS_H */ diff --git a/ports/winnt/ntpd/nt_ppsimpl.c b/ports/winnt/ntpd/nt_ppsimpl.c new file mode 100644 index 000000000..d3b3c5daa --- /dev/null +++ b/ports/winnt/ntpd/nt_ppsimpl.c @@ -0,0 +1,550 @@ +/* + * nt_ppsimpl.c - PPS API client implementation + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + * ---------------------------------------------------------------------- + * Most of this code is from the the original 'timepps.h' for windows + * where these functions where coded as 'inline'. While this was perhaps + * a convenient thing to do, using this amount of code as 'static inline' + * functions is generally a Bad Idea (tm). + * + * Not to mention that there are some static variables that got duplicated + * into the various modules... + */ + +#include + +#include /* offsetof() */ +#include /* _get_osfhandle() */ + +#include "timepps.h" +#include "ntp_stdlib.h" +#include "lib_strbuf.h" + +static ppsapi_provider * g_provider_list; +static ppsapi_provider * g_curr_provider; + +static pps_handle_t +internal_create_pps_handle( + void * prov_context + ) +{ + pps_unit_t * punit = NULL; + + if (NULL == g_curr_provider) + fprintf(stderr, "create_pps_handle: provider backend called me outside time_pps_create\n"); + else + punit = calloc(1, sizeof(pps_unit_t)); + + if (NULL != punit) { + punit->provider = g_curr_provider; + punit->context = prov_context; + punit->magic = PPSAPI_MAGIC_UNIT; + } + return (pps_handle_t)punit; +} + +static pps_unit_t * +unit_from_ppsapi_handle( + pps_handle_t handle + ) +{ + pps_unit_t *punit = (pps_unit_t *)handle; + if (!(punit && PPSAPI_MAGIC_UNIT == punit->magic)) + punit = NULL; + return punit; +} + +/* ntpd on Windows only looks to errno after finding 'GetLastError()' + * returns NO_ERROR. To accomodate its use of msyslog in portable code + * such as refclock_atom.c, this implementation always clears the + * Windows error code using 'SetLastError(NO_ERROR)' when returning an + * errno. This is also a good idea for any non-ntpd clients as they + * should rely only the errno for PPSAPI functions. + */ +static int +set_pps_errno( + int e +) +{ + SetLastError(NO_ERROR); + errno = e; + return -1; +} + + +/*Format a Windows errro into a temporary buffer from buffer lib */ +static char * +fmt_err( + DWORD ec + ) +{ + char * buff = NULL; + char * endp = NULL; + + /* get buffer & format message, ensure termination */ + LIB_GETBUF(buff); + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + ec, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buff, LIB_BUFLENGTH, + NULL); + buff[LIB_BUFLENGTH - 1] = '\0'; + /* strip trailing whitespace & CR/LF stuff & the trailing dot */ + endp = buff + strlen(buff); + while (endp != buff && endp[-1] <= ' ') + --endp; + if (endp != buff && endp[-1] == '.') + --endp; + *endp = '\0'; + /* If windows fails to format this, resort to numeric output... */ + if (!*buff) { + snprintf(buff, LIB_BUFLENGTH, + "(unknown windows error %lu / 0x%08lx)", + (unsigned long)ec, (unsigned long)ec); + } + /* That's it for now... */ + return buff; +} + +/* Cleanup & error return for actual loading steps */ +static int +cleanup_load( + ppsapi_provider * prov, + HMODULE hmod, + int errc +) +{ + /* if possible, decref the library handle */ + if (NULL != hmod) + FreeLibrary(hmod); + /* if possible, drop our provider structure */ + if (prov) { + free(prov->short_name); + free(prov->full_name); + free(prov); + } + /* error code pass-through */ + return errc; +} + +/* Get the directory path (!!) of the calling process. We want the true + * 8bit character version, and we should not trust '_pgmptr' or + * '_get_pgmptr()' too much. There's still some doubt around + * 'GetModuleFileNameA()', but all in all this seems to be the most + * reliable solution, even if it's a PITA with the buffer sizes. + */ +static char* +get_module_path(void) +{ + static const size_t s_smax = 4096; + + char * buff = NULL; + char * lsep; + DWORD slen, nlen; + + for (slen = 128; slen <= s_smax; slen <<= 1) { + buff = realloc(buff, slen); + if (NULL == buff) + goto fail; + nlen = GetModuleFileNameA(NULL, buff, slen); + if (0 == nlen) + goto fail; + if (nlen < slen) + break; + } + if (slen > s_smax) + goto fail; + lsep = strrchr(buff, '\\'); + if (NULL == lsep) + goto fail; + *++lsep = '\0'; + return realloc(buff, (size_t)(lsep - buff) + 1); + +fail: + free(buff); + return NULL; +} + +/* Iteration helper for the provider list. Naked names (without *any* + * path) will be prepended with path to the executable running this + * code. While this was not necessary until Win7, newer versions of + * Windows seem to have tighter restrictions from where to load code, at + * least as long as the binary is not signed. + */ +static char* +provlist_next_item( + const char ** const ppath + ) +{ + static char * s_modpath /* = NULL */; + static char s_nullstr[1] /* = { '\0' } */; + + const char * phead; + const char * ptail; + char * retv; + char * endp; + int/*BOOL*/ nodir; + int ch; + DWORD slen; + + /* check if we're already done */ + if (NULL == (phead = *ppath)) + return NULL; + /* Skip any leading ';' -- should not happen, but this is + * user-provided input after all... + */ + while (*phead == ';') + ++phead; + /* check if we're already done */ + if (!*phead) { + *ppath = NULL; + return NULL; + } + /* Inspect the next section of input string. */ + nodir = TRUE; + for (ptail = phead; (ch = *ptail) && ch != ';'; ++ptail) + if (ch == '\\' || ch == '/') + nodir = FALSE; + /* Make sure we have a proper module path when we need one. */ + if (nodir && NULL == s_modpath) { + s_modpath = get_module_path(); + if (NULL == s_modpath) + s_modpath = s_nullstr; + } + + /* Prepare buffer for copy of file name. */ + slen = (DWORD)(ptail - phead); /* 4GB string should be enough... */ + if (nodir && NULL != s_modpath) { + /* Prepend full path to executable to the name. */ + endp = retv = malloc(strlen(s_modpath) + slen + 1); + if (NULL != endp) { + strcpy(endp, s_modpath); + endp += strlen(endp); + } + } else { + endp = retv = malloc(slen + 1u); + } + /* Copy with conversion from '/' to '\\' */ + if (NULL != endp) { + while (phead != ptail) { + ch = (u_char)*phead++; + *endp++ = (ch != '/') ? ch : '\\'; + } + *endp = '\0'; + } + /*Update scan pointer & return result. */ + *ppath = (*ptail) ? (ptail + 1) : NULL; + return retv; +} + + +/* Try to load & init a provider DLL. (NOT a device instance!) */ +static int +load_pps_provider( + const char * dllpath + ) +{ + static const char msgfmt[] = "load_pps_provider: '%s': %s"; + + char short_name[16]; + char full_name[64]; + ppsapi_provider * prov = NULL; + HMODULE hmod = NULL; + pppsapi_prov_init pprov_init; + int errc; + + prov = calloc(1, sizeof(*prov)); + if (NULL == prov) { + errc = errno; + msyslog(LOG_WARNING, msgfmt, dllpath, + strerror(errc)); + return errc; + } + + hmod = LoadLibraryA(dllpath); + if (NULL == hmod) { + msyslog(LOG_WARNING, msgfmt, dllpath, + fmt_err(GetLastError())); + return cleanup_load(prov, hmod, ENOENT); + } + + pprov_init = (pppsapi_prov_init)GetProcAddress(hmod, "ppsapi_prov_init"); + if (NULL == pprov_init) { + msyslog(LOG_WARNING, msgfmt, dllpath, + "main entry point not found"); + return cleanup_load(prov, hmod, EFAULT); + } + + prov->caps = (*pprov_init)(PPSAPI_TIMEPPS_PROV_VER, + &internal_create_pps_handle, + &pps_ntp_timestamp_from_counter, + short_name, sizeof(short_name), + full_name, sizeof(full_name)); + if (!prov->caps) { + msyslog(LOG_WARNING, msgfmt, dllpath, + "no capabilities"); + return cleanup_load(prov, hmod, EACCES); + } + + prov->short_name = (*short_name) ? _strdup(short_name) : NULL; + prov->full_name = (*full_name ) ? _strdup(full_name ) : NULL; + if (NULL == prov->short_name || NULL == prov->full_name) { + msyslog(LOG_WARNING, msgfmt, dllpath, + "missing names"); + return cleanup_load(prov, hmod, EINVAL); + } + + prov->ptime_pps_create = (provtime_pps_create) + GetProcAddress(hmod, "prov_time_pps_create"); + prov->ptime_pps_destroy = (provtime_pps_destroy) + GetProcAddress(hmod, "prov_time_pps_destroy"); + prov->ptime_pps_setparams = (provtime_pps_setparams) + GetProcAddress(hmod, "prov_time_pps_setparams"); + prov->ptime_pps_fetch = (provtime_pps_fetch) + GetProcAddress(hmod, "prov_time_pps_fetch"); + prov->ptime_pps_kcbind = (provtime_pps_kcbind) + GetProcAddress(hmod, "prov_time_pps_kcbind"); + + if (NULL == prov->ptime_pps_create || + NULL == prov->ptime_pps_destroy || + NULL == prov->ptime_pps_setparams || + NULL == prov->ptime_pps_fetch || + NULL == prov->ptime_pps_kcbind ) + { + msyslog(LOG_WARNING, msgfmt, prov->short_name, + "missing entry point"); + return cleanup_load(prov, hmod, EINVAL); + } + + prov->next = g_provider_list; + g_provider_list = prov; + + return 0; +} + + +int +time_pps_create( + int filedes,/* device file descriptor */ + pps_handle_t * phandle /* returned handle */ + ) +{ + HANDLE winhandle; + const char * dlls; + char * dll; + ppsapi_provider * prov; + pps_handle_t ppshandle; + int err; + + if (NULL == phandle) + return set_pps_errno(EFAULT); + + winhandle = (HANDLE)_get_osfhandle(filedes); + if (INVALID_HANDLE_VALUE == winhandle) + return set_pps_errno(EBADF); + + /* For initial testing the list of PPSAPI backend providers is + * provided by the environment variable PPSAPI_DLLS, separated by + * semicolons such as + * PPSAPI_DLLS=c:\ntp\serial_ppsapi.dll;..\parport_ppsapi.dll + * There are a million better ways, such as a well-known registry + * key under which a value is created for each provider DLL + * installed, or even a platform-specific ntp.conf directive or + * command-line switch. + * + * [Bug 3139] Since nothing is more durable than a provisional + * implementation, we're still stuck with that... + */ + dlls = getenv("PPSAPI_DLLS"); + if (NULL != dlls && NULL == g_provider_list) { + msyslog(LOG_INFO, "time_pps_create: load list '%s'", + dlls); + } else + dlls = NULL; + + while (NULL != (dll = provlist_next_item(&dlls))) { + err = load_pps_provider(dll); + if (err) { + msyslog(LOG_ERR, "time_pps_create: load failed (%s) --> %d / %s", + dll, err, strerror(err)); + } else { + msyslog(LOG_INFO, "time_pps_create: loaded '%s'", + dll); + } + free(dll); + } + + /* Hand off to each provider in turn until one returns a PPS + * handle or they've all declined. + * + * [Bug 3139] Since we potentially tried a series of DLLs, it's + * a good question what the returned error should be if all of + * them failed; Returning the error from the last attempt is as + * good as any but for single DLL (which is the normal case) + * this provides slightly more information. + */ + err = ENOEXEC; + if (NULL == g_provider_list) { + msyslog(LOG_ERR, "time_pps_create: %s", + "no providers available"); + return set_pps_errno(err); + } + for (prov = g_provider_list; NULL != prov; prov = prov->next) { + ppshandle = 0; + g_curr_provider = prov; + err = (*prov->ptime_pps_create)(winhandle, &ppshandle); + g_curr_provider = NULL; + if (!err && ppshandle) { + *phandle = ppshandle; + return 0; + } + msyslog(LOG_INFO, "time_pps_create: provider '%s' failed: %d / %s", + prov->short_name, err, strerror(err)); + } + msyslog(LOG_ERR, "time_pps_create: %s", + "all providers failed"); + return set_pps_errno(err); +} + + +int +time_pps_destroy( + pps_handle_t handle + ) +{ + pps_unit_t * punit = unit_from_ppsapi_handle(handle); + int err = 0; + + /* Check for valid arguments */ + if (NULL == punit) + return set_pps_errno(EBADF); + /* Call provider. Note the handle is gone anyway... */ + err = (*punit->provider->ptime_pps_destroy)(punit, punit->context); + free(punit); + if (err) + return set_pps_errno(err); + return 0; +} + + +int +time_pps_setparams( + pps_handle_t handle, + const pps_params_t *params + ) +{ + pps_unit_t * punit = unit_from_ppsapi_handle(handle); + int err = 0; + + /* Check for valid arguments */ + if (NULL == punit) + return set_pps_errno(EBADF); + if (NULL == params) + return set_pps_errno(EFAULT); + /* Call provider */ + err = (*punit->provider->ptime_pps_setparams)(punit, punit->context, params); + if (err) + return set_pps_errno(err); + return 0; +} + + +int +time_pps_getparams( + pps_handle_t handle, + pps_params_t * params_buf + ) +{ + pps_unit_t * punit = unit_from_ppsapi_handle(handle); + + /* Check for valid arguments */ + punit; + if (NULL == punit) + return set_pps_errno(EBADF); + if (NULL == params_buf) + return set_pps_errno(EFAULT); + /* Copy out parameters */ + *params_buf = punit->params; + return 0; +} + + +int +time_pps_getcap( + pps_handle_t handle, + int * pmode + ) +{ + pps_unit_t * punit = unit_from_ppsapi_handle(handle); + + /* Check for valid arguments */ + if (NULL == punit) + return set_pps_errno(EBADF); + if (NULL == pmode) + return set_pps_errno(EFAULT); + /* Copy out capabilities */ + *pmode = punit->provider->caps; + return 0; +} + + +int +time_pps_fetch( + pps_handle_t handle, + const int tsformat, + pps_info_t * pinfo, + const struct timespec * ptimeout + ) +{ + pps_unit_t * punit = unit_from_ppsapi_handle(handle); + int err = 0; + + /* Check for valid arguments */ + if (NULL == punit) + return set_pps_errno(EBADF); + if (NULL == pinfo) + return set_pps_errno(EFAULT); + /* Fetch timestamps */ + err = (*punit->provider->ptime_pps_fetch)(punit, + punit->context, + tsformat, + pinfo, + ptimeout); + + if (err) + return set_pps_errno(err); + return 0; +} + + +int +time_pps_kcbind( + pps_handle_t handle, + const int kernel_consumer, + const int edge, const int tsformat + ) +{ + pps_unit_t * punit = unit_from_ppsapi_handle(handle); + int err = 0; + + /* Check for valid arguments */ + if (NULL == punit) + return set_pps_errno(EBADF); + /* Call provider */ + err = (*punit->provider->ptime_pps_kcbind)( + punit, + punit->context, + kernel_consumer, + edge, + tsformat); + + if (err) + return set_pps_errno(err); + return 0; +} + +/* -*- that's all folks! -*- */ diff --git a/ports/winnt/vs2005/ntpd.vcproj b/ports/winnt/vs2005/ntpd.vcproj index 7768a385b..3d730c0b4 100644 --- a/ports/winnt/vs2005/ntpd.vcproj +++ b/ports/winnt/vs2005/ntpd.vcproj @@ -252,6 +252,10 @@ /> + + diff --git a/ports/winnt/vs2008/ntpd/ntpd.vcproj b/ports/winnt/vs2008/ntpd/ntpd.vcproj index 90cd2dd6c..107cf8724 100644 --- a/ports/winnt/vs2008/ntpd/ntpd.vcproj +++ b/ports/winnt/vs2008/ntpd/ntpd.vcproj @@ -315,6 +315,10 @@ RelativePath="..\..\ntpd\nt_clockstuff.c" > + + diff --git a/ports/winnt/vs2013/ntpd/ntpd.vcxproj b/ports/winnt/vs2013/ntpd/ntpd.vcxproj index 8d6b2fa3d..0fd27b54a 100644 --- a/ports/winnt/vs2013/ntpd/ntpd.vcxproj +++ b/ports/winnt/vs2013/ntpd/ntpd.vcxproj @@ -338,6 +338,7 @@ + diff --git a/ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters b/ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters index 653788102..ee251fb97 100644 --- a/ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters +++ b/ports/winnt/vs2013/ntpd/ntpd.vcxproj.filters @@ -297,6 +297,9 @@ Source Files + + Source Files + diff --git a/ports/winnt/vs2015/ntpd/ntpd.vcxproj b/ports/winnt/vs2015/ntpd/ntpd.vcxproj index 2af43a708..8114a3c43 100644 --- a/ports/winnt/vs2015/ntpd/ntpd.vcxproj +++ b/ports/winnt/vs2015/ntpd/ntpd.vcxproj @@ -338,6 +338,7 @@ + diff --git a/ports/winnt/vs2015/ntpd/ntpd.vcxproj.filters b/ports/winnt/vs2015/ntpd/ntpd.vcxproj.filters index 653788102..ee251fb97 100644 --- a/ports/winnt/vs2015/ntpd/ntpd.vcxproj.filters +++ b/ports/winnt/vs2015/ntpd/ntpd.vcxproj.filters @@ -297,6 +297,9 @@ Source Files + + Source Files +