+---
+* [Bug 3432] refclocks that 'write()' should check the result <perlinger@ntp.org>
+ - plus some more work on warnings for unchecked results
+
---
(4.2.8p11) 2018/02/27 Released by Harlan Stenn <stenn@ntp.org>
extern int io_addclock (struct refclockio *);
extern void io_closeclock (struct refclockio *);
+#define FDWRITE_ERROR ((size_t)-1)
+
#ifdef REFCLOCK
extern void refclock_buginfo(sockaddr_u *,
struct refclockbug *);
extern void refclock_report (struct peer *, int);
extern int refclock_gtlin (struct recvbuf *, char *, int, l_fp *);
extern int refclock_gtraw (struct recvbuf *, char *, int, l_fp *);
+extern size_t refclock_write (const struct peer *, const void *, size_t,
+ const char * what);
+extern size_t refclock_fdwrite(const struct peer *, int, const void *, size_t,
+ const char * what);
extern int indicate_refclock_packet(struct refclockio *,
struct recvbuf *);
extern void process_refclock_packet(struct recvbuf *);
extern const char * socktohost (const sockaddr_u *);
extern int octtoint (const char *, u_long *);
extern u_long ranp2 (int);
-extern const char *refnumtoa (sockaddr_u *);
+extern const char *refnumtoa (const sockaddr_u *);
extern const char *refid_str (u_int32, int);
extern int decodenetnum (const char *, sockaddr_u *);
const char *
refnumtoa(
- sockaddr_u *num
+ const sockaddr_u *num
)
{
u_int32 netnum;
return (bmax);
}
+/*
+ * refclock_fdwrite()
+ *
+ * Write data to a clock device. Does the necessary result checks and
+ * logging, and encapsulates OS dependencies.
+ */
+#ifdef SYS_WINNT
+extern int async_write(int fd, const void * buf, unsigned int len);
+#endif
+
+size_t
+refclock_fdwrite(
+ const struct peer * peer,
+ int fd,
+ const void * buf,
+ size_t len,
+ const char * what
+ )
+{
+ size_t nret, nout;
+ int nerr;
+
+ nout = (INT_MAX > len) ? len : INT_MAX;
+# ifdef SYS_WINNT
+ nret = (size_t)async_write(fd, buf, (unsigned int)nout);
+# else
+ nret = (size_t)write(fd, buf, nout);
+# endif
+ if (NULL != what) {
+ if (nret == FDWRITE_ERROR) {
+ nerr = errno;
+ msyslog(LOG_INFO,
+ "%s: write %s failed, fd=%d, %m",
+ refnumtoa(&peer->srcadr), what,
+ fd);
+ errno = nerr;
+ } else if (nret != len) {
+ nerr = errno;
+ msyslog(LOG_NOTICE,
+ "%s: %s shortened, fd=%d, wrote %zu of %zu bytes",
+ refnumtoa(&peer->srcadr), what,
+ fd, nret, len);
+ errno = nerr;
+ }
+ }
+ return nret;
+}
+
+size_t
+refclock_write(
+ const struct peer * peer,
+ const void * buf,
+ size_t len,
+ const char * what
+ )
+{
+ if ( ! (peer && peer->procptr)) {
+ if (NULL != what)
+ msyslog(LOG_INFO,
+ "%s: write %s failed, invalid clock peer",
+ refnumtoa(&peer->srcadr), what);
+ errno = EINVAL;
+ return FDWRITE_ERROR;
+ }
+ return refclock_fdwrite(peer, peer->procptr->io.fd,
+ buf, len, what);
+}
/*
* indicate_refclock_packet()
# include <sys/ioctl.h>
#endif /* HAVE_SYS_IOCTL_H */
-#ifdef SYS_WINNT
-#undef write /* ports/winnt/include/config.h: #define write _write */
-extern int async_write(int, const void *, unsigned int);
-#define write(fd, data, octets) async_write(fd, data, octets)
-#endif
-
/*
* This driver supports the US (NIST, USNO) and European (PTB, NPL,
* etc.) modem time services, as well as Spectracom GPS and WWVB
*up->bufptr++ = *tptr;
if (*tptr == '*' || *tptr == '#') {
up->tstamp = pp->lastrec;
- if (write(pp->io.fd, tptr, 1) < 0)
- msyslog(LOG_ERR, "acts: write echo fails %m");
+ refclock_write(peer, tptr, 1, "data");
}
}
}
up->retry, sys_phone[up->retry]);
if (ioctl(pp->io.fd, TIOCMBIS, &dtr) < 0)
msyslog(LOG_ERR, "acts: ioctl(TIOCMBIS) failed: %m");
- if (write(pp->io.fd, sys_phone[up->retry],
- strlen(sys_phone[up->retry])) < 0)
- msyslog(LOG_ERR, "acts: write DIAL fails %m");
- write(pp->io.fd, "\r", 1);
+ refclock_write(peer, sys_phone[up->retry],
+ strlen(sys_phone[up->retry]),
+ "DIAL");
+ refclock_write(peer, "\r", 1, "CR");
up->retry++;
up->state = S_CONNECT;
up->timer = ANSWER;
struct actsunit *up;
struct refclockproc *pp;
int fd;
- int rc;
char device[20];
char lockfile[128], pidbuf[8];
* the modem business and send 'T' for Spectrabum.
*/
if (sys_phone[up->retry] == NULL) {
- if (write(pp->io.fd, "T", 1) < 0)
- msyslog(LOG_ERR, "acts: write T fails %m");
+ refclock_write(peer, "T", 1, "T");
up->state = S_MSG;
up->timer = TIMECODE;
return;
*/
mprintf_event(PEVNT_CLOCK, peer, "SETUP %s",
modem_setup);
- rc = write(pp->io.fd, modem_setup, strlen(modem_setup));
- if (rc < 0)
- msyslog(LOG_ERR, "acts: write SETUP fails %m");
- write(pp->io.fd, "\r", 1);
+ refclock_write(peer, modem_setup, strlen(modem_setup),
+ "SETUP");
+ refclock_write(peer, "\r", 1, "CR");
up->state = S_SETUP;
up->timer = SETUP;
return;
#include <stdio.h>
#include <ctype.h>
-#ifdef SYS_WINNT
-extern int async_write(int, const void *, unsigned int);
-#undef write
-#define write(fd, data, octets) async_write(fd, data, octets)
-#endif
-
/*
* This driver supports the Arbiter 1088A/B Satellite Controlled Clock.
* The claimed accuracy of this clock is 100 ns relative to the PPS
#ifdef DEBUG
if(debug) { printf("arbiter: mode = %d.\n", peer->MODE); }
#endif
- write(pp->io.fd, COMMAND_HALT_BCAST, 2);
+ refclock_write(peer, COMMAND_HALT_BCAST, 2, "HALT_BCAST");
return (1);
}
*/
if (!strncmp(tbuf, "TQ", 2)) {
up->qualchar = tbuf[2];
- write(pp->io.fd, "SR", 2);
+ refclock_write(peer, "SR", 2, "SR");
return;
} else if (!strncmp(tbuf, "SR", 2)) {
strlcpy(up->status, tbuf + 2,
sizeof(up->status));
if (pp->sloppyclockflag & CLK_FLAG4)
- write(pp->io.fd, "LA", 2);
+ refclock_write(peer, "LA", 2, "LA");
else
- write(pp->io.fd, COMMAND_START_BCAST, 2);
+ refclock_write(peer, COMMAND_START_BCAST, 2,
+ COMMAND_START_BCAST);
return;
} else if (!strncmp(tbuf, "LA", 2)) {
strlcpy(up->latlon, tbuf + 2, sizeof(up->latlon));
- write(pp->io.fd, "LO", 2);
+ refclock_write(peer, "LO", 2, "LO");
return;
} else if (!strncmp(tbuf, "LO", 2)) {
strlcat(up->latlon, " ", sizeof(up->latlon));
strlcat(up->latlon, tbuf + 2, sizeof(up->latlon));
- write(pp->io.fd, "LH", 2);
+ refclock_write(peer, "LH", 2, "LH");
return;
} else if (!strncmp(tbuf, "LH", 2)) {
strlcat(up->latlon, " ", sizeof(up->latlon));
strlcat(up->latlon, tbuf + 2, sizeof(up->latlon));
- write(pp->io.fd, "DB", 2);
+ refclock_write(peer, "DB", 2, "DB");
return;
} else if (!strncmp(tbuf, "DB", 2)) {
if (debug)
printf("arbiter: %s\n", up->latlon);
#endif
- write(pp->io.fd, COMMAND_START_BCAST, 2);
+ refclock_write(peer, COMMAND_START_BCAST, 2,
+ COMMAND_START_BCAST);
}
}
&syncchar, &pp->year, &pp->day, &pp->hour,
&pp->minute, &pp->second) != 6) {
refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, COMMAND_HALT_BCAST, 2);
+ refclock_write(peer, COMMAND_HALT_BCAST, 2, COMMAND_HALT_BCAST);
return;
}
case 'F': /* clock failure */
pp->disp = MAXDISPERSE;
refclock_report(peer, CEVNT_FAULT);
- write(pp->io.fd, COMMAND_HALT_BCAST, 2);
+ refclock_write(peer, COMMAND_HALT_BCAST, 2,
+ COMMAND_HALT_BCAST);
return;
default:
pp->disp = MAXDISPERSE;
refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, COMMAND_HALT_BCAST, 2);
+ refclock_write(peer, COMMAND_HALT_BCAST, 2,
+ COMMAND_HALT_BCAST);
return;
}
if (syncchar != ' ')
refclock_receive(peer);
/* if (up->tcswitch >= MAXSTAGE) { */
- write(pp->io.fd, COMMAND_HALT_BCAST, 2);
+ refclock_write(peer, COMMAND_HALT_BCAST, 2, COMMAND_HALT_BCAST);
/* } */
}
up = pp->unitptr;
pp->polls++;
up->tcswitch = 0;
- if (write(pp->io.fd, "TQ", 2) != 2)
+ if (refclock_write(peer, "TQ", 2, "TQ") != 2)
refclock_report(peer, CEVNT_FAULT);
/*
memcpy(up->lastptr, stat_command[up->index], octets);
up->lastptr += octets - 1;
*up->lastptr = '\0';
- (void)write(pp->io.fd, stat_command[up->index],
- strlen(stat_command[up->index]));
+ refclock_write(peer, stat_command[up->index],
+ strlen(stat_command[up->index]),
+ "command");
up->index++;
if (*stat_command[up->index] == '\0')
up->index = 0;
#include <stdio.h>
#include <ctype.h>
-#ifdef SYS_WINNT
-extern int async_write(int, const void *, unsigned int);
-#undef write
-#define write(fd, data, octets) async_write(fd, data, octets)
-#endif
-
/*
* This driver supports a generic dumb clock that only outputs hh:mm:ss,
* in local time, no less.
pollchar = 'R';
else
pollchar = 'T';
- if (write(pp->io.fd, &pollchar, 1) != 1)
+ if (refclock_fdwrite(peer, pp->io.fd, &pollchar, 1) != 1)
refclock_report(peer, CEVNT_FAULT);
else
pp->polls++;
/* The logon string is actually the ?WATCH command of GPSD,
* using JSON data and selecting the GPS device name we created
- * from our unit number. We have an old a newer version that
+ * from our unit number. We have an old and a newer version that
* request PPS (and TOFF) transmission.
*/
snprintf(up->buffer, sizeof(up->buffer),
if (ioctl(pp->io.fd, TIOCMBIC, (char *)&bits) < 0)
refclock_report(peer, CEVNT_FAULT);
get_systime(&pp->lastrec);
- if (write(pp->io.fd, "T", 1) != 1)
+ if (refclock_write(peer, "T", 1, "T") != 1)
refclock_report(peer, CEVNT_FAULT);
ioctl(pp->io.fd, TIOCMBIS, (char *)&bits);
if (pp->coderecv == pp->codeproc) {
# include <sys/ioctl.h>
#endif
-#ifdef SYS_WINNT
-extern int async_write(int, const void *, unsigned int);
-#undef write
-#define write(fd, data, octets) async_write(fd, data, octets)
-#endif
-
/*
* clock definitions
*/
* and get the local timezone information
*/
up->linecnt = 1;
- if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20)
- refclock_report(peer, CEVNT_FAULT);
+ if (refclock_write(peer, "*IDN?\r:PTIME:TZONE?\r", 20, NULL) != 20)
+ refclock_report(peer, CEVNT_FAULT);
return (1);
}
if (strrchr(prompt,'E') > strrchr(prompt,'s')){
#ifdef DEBUG
if (debug)
- printf("hpgps: error indicated in prompt: %s\n", prompt);
+ printf("hpgps: error indicated in prompt: %s\n", prompt);
#endif
- if (write(pp->io.fd, "*CLS\r\r", 6) != 6)
- refclock_report(peer, CEVNT_FAULT);
+ if (refclock_write(peer, "*CLS\r\r", 6, NULL) != 6)
+ refclock_report(peer, CEVNT_FAULT);
}
/*
*/
if (pp->sloppyclockflag & CLK_FLAG4){
up->linecnt = 22;
- if (write(pp->io.fd, ":SYSTEM:PRINT?\r", 15) != 15)
- refclock_report(peer, CEVNT_FAULT);
+ if (refclock_write(peer, ":SYSTEM:PRINT?\r", 15, NULL) != 15)
+ refclock_report(peer, CEVNT_FAULT);
}
}
refclock_report(peer, CEVNT_TIMEOUT);
else
up->pollcnt--;
- if (write(pp->io.fd, ":PTIME:TCODE?\r", 14) != 14) {
+ if (refclock_write(peer, ":PTIME:TCODE?\r", 14, NULL) != 14) {
refclock_report(peer, CEVNT_FAULT);
}
else
* support functions by defining NMEA_WRITE_SUPPORT to non-zero...
*/
#if NMEA_WRITE_SUPPORT
-
static void gps_send(int, const char *, struct peer *);
-# ifdef SYS_WINNT
-# undef write /* ports/winnt/include/config.h: #define write _write */
-extern int async_write(int, const void *, unsigned int);
-# define write(fd, data, octets) async_write(fd, data, octets)
-# endif /* SYS_WINNT */
-
#endif /* NMEA_WRITE_SUPPORT */
static int32_t g_gpsMinBase;
len - 2, cmd));
/* send out the whole stuff */
- if (write(fd, cmd, len) == -1)
+ if (refclock_fdwrite(peer, fd, cmd, len) != len)
refclock_report(peer, CEVNT_FAULT);
}
#endif /* NMEA_WRITE_SUPPORT */
shmem_old_size = sbuf.st_size;
if (shmem_old_size != 0) {
shmem_old = emalloc((unsigned) sbuf.st_size);
- read(fd, shmem_old, shmem_old_size);
+ if (read(fd, shmem_old, shmem_old_size) != shmem_old_size)
+ oncore_log(instance, LOG_WARNING,
+ "ONCORE: truncated/failed read of SHMEM file");
}
close(fd);
}
if (!strncmp((char *) cp, "@@Cb", 4) &&
oncore_checksum_ok(cp, 33) &&
(*(cp+4) == 4 || *(cp+4) == 5)) {
- write(instance->ttyfd, cp, n);
+ refclock_fdwrite(instance->peer, instance->ttyfd,
+ cp, n, "data");
oncore_print_Cb(instance, cp);
}
}
{
int fd;
u_char cs = 0;
+ const struct peer * peer;
- fd = instance->ttyfd;
+ fd = instance->ttyfd;
+ peer = instance->peer;
#ifdef ONCORE_VERBOSE_SENDMSG
if (debug > 4) {
oncore_log_f(instance, LOG_DEBUG, "ONCORE: Send @@%c%c %d",
ptr[0], ptr[1], (int)len);
}
#endif
- write(fd, "@@", (size_t) 2);
- write(fd, ptr, len);
+ refclock_fdwrite(peer, fd, "@@", (size_t)2, "data");
+ refclock_fdwrite(peer, fd, ptr, len, "data");
while (len--)
cs ^= *ptr++;
- write(fd, &cs, (size_t) 1);
- write(fd, "\r\n", (size_t) 2);
+ refclock_fdwrite(peer, fd, &cs, (size_t)1, "data");
+ refclock_fdwrite(peer, fd, "\r\n", (size_t)2, "data");
}
return; /* using synchronous packet input */
if(up->type == CLK_PRAECIS) {
- if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
+ if (write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) {
msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
- else {
+ } else {
praecis_msg = 1;
return;
}
/* Edge trigger */
if (up->type == CLK_ACUTIME)
- write (pp->io.fd, "", 1);
+ if (write (pp->io.fd, "", 1) != 1)
+ msyslog(LOG_WARNING,
+ "Palisade(%d) HW_poll: failed to send trigger: %m",
+ up->unit);
if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
#ifdef DEBUG
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
-#ifdef SYS_WINNT
-extern int async_write(int, const void *, unsigned int);
-#undef write
-#define write(fd, data, octets) async_write(fd, data, octets)
-#endif
-
/* This should be an atom clock but those are very hard to build.
*
* The PCL720 from P C Labs has an Intel 8253 lookalike, as well as a bunch
size_t len = strlen(cmd);
true_debug(peer, "Send '%s'\n", cmd);
- if (write(pp->io.fd, cmd, (unsigned)len) != len)
+ if (refclock_write(peer, cmd, len, NULL) != len)
refclock_report(peer, CEVNT_FAULT);
else
pp->polls++;
{
int idrift = 0, fdrift = 0;
- fscanf(df, "%4d.%03d", &idrift, &fdrift);
+ if (2 != fscanf(df, "%4d.%03d", &idrift, &fdrift))
+ LPRINTF("read_drift: trouble reading drift file");
fclose(df);
LPRINTF("read_drift: %d.%03d ppm ", idrift, fdrift);
)
{
# ifdef HAVE_DAEMON
- daemon(0, 0);
+ if (daemon(0, 0)) {
+ fprintf(stderr, "'daemon()' fails: %d(%s)\n",
+ errno, strerror(errno));
+ }
# else /* not HAVE_DAEMON */
if (fork())
exit(0);
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4307;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4307;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4307;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4307;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="..\..\..\..\ntpd\refclock_as2201.c" />
<ClCompile Include="..\..\..\..\ntpd\refclock_atom.c" />
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
+#include "lib_strbuf.h"
#include "unity.h"
#include "test-libntp.h"
#include <string.h>
-char * CalendarToString(const struct calendar cal);
-int IsEqual(const struct calendar expected, const struct calendar actual);
void setUp(void);
void tearDown(void);
void test_RegularTime(void);
void test_uLongWrapped(void);
-char *
+static const char *
CalendarToString(const struct calendar cal)
{
- char * str = emalloc (sizeof (char) * 100);
- char buffer[100] ="";
-
- *str = '\0';
- snprintf(buffer, 100, "%u", cal.year);
- strcat(str, buffer);
- strcat(str, "-");
- snprintf(buffer, 100, "%u", (u_int)cal.month);
- strcat(str, buffer);
- strcat(str, "-");
- snprintf(buffer, 100, "%u", (u_int)cal.monthday);
- strcat(str, buffer);
- strcat(str, " (");
- snprintf(buffer, 100, "%u", (u_int) cal.yearday);
- strcat(str, buffer);
- strcat(str, ") ");
- snprintf(buffer, 100, "%u", (u_int)cal.hour);
- strcat(str, buffer);
- strcat(str, ":");
- snprintf(buffer, 100, "%u", (u_int)cal.minute);
- strcat(str, buffer);
- strcat(str, ":");
- snprintf(buffer, 100, "%u", (u_int)cal.second);
- strcat(str, buffer);
+ char * str;
+
+ LIB_GETBUF(str);
+ snprintf(str, LIB_BUFLENGTH,
+ "%04hu-%02hhu-%02hhu (%hu) %02hhu:%02hhu:%02hhu",
+ cal.year, cal.month, cal.monthday, cal.yearday,
+ cal.hour, cal.minute, cal.second);
return str;
}
-int // technically boolean
+static int // technically boolean
IsEqual(const struct calendar expected, const struct calendar actual)
{
if ( expected.year == actual.year
&& expected.second == actual.second) {
return TRUE;
} else {
- char *p_exp, *p_act;
-
- p_exp = CalendarToString(expected);
- p_act = CalendarToString(actual);
+ const char * p_exp = CalendarToString(expected);
+ const char * p_act = CalendarToString(actual);
printf("expected: %s but was %s", p_exp, p_act);
- free(p_exp);
- free(p_act);
return FALSE;
}
}
-void
-setUp()
+void setUp(void)
{
ntpcal_set_timefunc(timefunc);
settime(1970, 1, 1, 0, 0, 0);
init_lib();
-
- return;
}
-void
-tearDown()
+void tearDown(void)
{
ntpcal_set_timefunc(NULL);
-
- return;
}
-void
-test_RegularTime(void)
+void test_RegularTime(void)
{
u_long testDate = 3485080800UL; // 2010-06-09 14:00:00
struct calendar expected = {2010,160,6,9,14,0,0};
caljulian(testDate, &actual);
TEST_ASSERT_TRUE(IsEqual(expected, actual));
-
- return;
}
-void
-test_LeapYear(void)
+void test_LeapYear(void)
{
u_long input = 3549902400UL; // 2012-06-28 20:00:00Z
struct calendar expected = {2012, 179, 6, 28, 20, 0, 0};
caljulian(input, &actual);
TEST_ASSERT_TRUE(IsEqual(expected, actual));
-
- return;
}
-void
-test_uLongBoundary(void)
+void test_uLongBoundary(void)
{
u_long enc_time = 4294967295UL; // 2036-02-07 6:28:15
struct calendar expected = {2036,0,2,7,6,28,15};
caljulian(enc_time, &actual);
TEST_ASSERT_TRUE(IsEqual(expected, actual));
-
- return;
}
-void
-test_uLongWrapped(void)
+void test_uLongWrapped(void)
{
u_long enc_time = 0;
struct calendar expected = {2036,0,2,7,6,28,16};
caljulian(enc_time, &actual);
TEST_ASSERT_TRUE(IsEqual(expected, actual));
-
- return;
}
#include "config.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
+#include "lib_strbuf.h"
#include "test-libntp.h"
#include <string.h>
progname = argv[0];
suite_setup();
UnityBegin("caljulian.c");
- RUN_TEST(test_RegularTime, 16);
- RUN_TEST(test_LeapYear, 17);
- RUN_TEST(test_uLongBoundary, 18);
- RUN_TEST(test_uLongWrapped, 19);
+ RUN_TEST(test_RegularTime, 15);
+ RUN_TEST(test_LeapYear, 16);
+ RUN_TEST(test_uLongBoundary, 17);
+ RUN_TEST(test_uLongWrapped, 18);
return (UnityEnd());
}