From: Florian Forster Date: Thu, 3 Jul 2008 09:39:13 +0000 (+0200) Subject: src/rrd_daemon.c: Use `sread' and `swrite' instead of read(2) and write(2). X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=commitdiff_plain;h=d4dc16f8b4746f862477a44c953e5198546d41ec src/rrd_daemon.c: Use `sread' and `swrite' instead of read(2) and write(2). The ``secure'' sread assures that the received string ends with a newline, strips it off the buffer and assures that the returned buffer is null terminated. swrite returns success only if all bytes could be written. --- diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c index 7a51f5d..ac974ed 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -223,6 +223,84 @@ static int remove_pidfile (void) /* {{{ */ return (errno); } /* }}} int remove_pidfile */ +static ssize_t sread (int fd, void *buffer_void, size_t buffer_size) /* {{{ */ +{ + char *buffer; + size_t buffer_used; + size_t buffer_free; + ssize_t status; + + buffer = (char *) buffer_void; + buffer_used = 0; + buffer_free = buffer_size; + + while (buffer_free > 0) + { + status = read (fd, buffer + buffer_used, buffer_free); + if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR))) + continue; + + if (status < 0) + return (-1); + + if (status == 0) + return (0); + + assert ((0 > status) || (buffer_free >= (size_t) status)); + + buffer_free = buffer_free - status; + buffer_used = buffer_used + status; + + if (buffer[buffer_used - 1] == '\n') + break; + } + + assert (buffer_used > 0); + + if (buffer[buffer_used - 1] != '\n') + { + errno = ENOBUFS; + return (-1); + } + + buffer[buffer_used - 1] = 0; + + /* Fix network line endings. */ + if ((buffer_used > 1) && (buffer[buffer_used - 2] == '\r')) + { + buffer_used--; + buffer[buffer_used - 1] = 0; + } + + return (buffer_used); +} /* }}} ssize_t sread */ + +static ssize_t swrite (int fd, const void *buf, size_t count) /* {{{ */ +{ + const char *ptr; + size_t nleft; + ssize_t status; + + ptr = (const char *) buf; + nleft = count; + + while (nleft > 0) + { + status = write (fd, (const void *) ptr, nleft); + + if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR))) + continue; + + if (status < 0) + return (status); + + nleft = nleft - status; + ptr = ptr + status; + } + + return (0); +} /* }}} ssize_t swrite */ + /* * enqueue_cache_item: * `cache_lock' must be acquired before calling this function! @@ -687,11 +765,11 @@ static int handle_request_help (int fd, /* {{{ */ for (i = 0; i < help_text_len; i++) { - status = write (fd, help_text[i], strlen (help_text[i])); + status = swrite (fd, help_text[i], strlen (help_text[i])); if (status < 0) { status = errno; - RRDD_LOG (LOG_ERR, "handle_request_help: write(2) returned an error."); + RRDD_LOG (LOG_ERR, "handle_request_help: swrite returned an error."); return (status); } } @@ -726,11 +804,11 @@ static int handle_request_stats (int fd, /* {{{ */ #define RRDD_STATS_SEND \ outbuf[sizeof (outbuf) - 1] = 0; \ - status = write (fd, outbuf, strlen (outbuf)); \ + status = swrite (fd, outbuf, strlen (outbuf)); \ if (status < 0) \ { \ status = errno; \ - RRDD_LOG (LOG_INFO, "handle_request_stats: write(2) returned an error."); \ + RRDD_LOG (LOG_INFO, "handle_request_stats: swrite returned an error."); \ return (status); \ } @@ -786,11 +864,11 @@ static int handle_request_flush (int fd, /* {{{ */ } result[sizeof (result) - 1] = 0; - status = write (fd, result, strlen (result)); + status = swrite (fd, result, strlen (result)); if (status < 0) { status = errno; - RRDD_LOG (LOG_INFO, "handle_request_flush: write(2) returned an error."); + RRDD_LOG (LOG_INFO, "handle_request_flush: swrite returned an error."); return (status); } @@ -895,14 +973,15 @@ static int handle_request_update (int fd, /* {{{ */ pthread_mutex_unlock (&cache_lock); - snprintf (answer, sizeof (answer), "0 Enqueued %i value(s)\n", values_num); + snprintf (answer, sizeof (answer), "0 Enqueued %i value%s\n", values_num, + (values_num == 1) ? "" : "s"); answer[sizeof (answer) - 1] = 0; - status = write (fd, answer, strlen (answer)); + status = swrite (fd, answer, strlen (answer)); if (status < 0) { status = errno; - RRDD_LOG (LOG_INFO, "handle_request_update: write(2) returned an error."); + RRDD_LOG (LOG_INFO, "handle_request_update: swrite returned an error."); return (status); } @@ -917,31 +996,19 @@ static int handle_request (int fd) /* {{{ */ char *command; int status; - status = read (fd, buffer, sizeof (buffer)); + status = (int) sread (fd, buffer, sizeof (buffer)); if (status == 0) { return (1); } else if (status < 0) { - RRDD_LOG (LOG_ERR, "handle_request: read(2) failed."); - return (-1); - } - buffer_size = status; - assert (((size_t) buffer_size) <= sizeof (buffer)); - - if (buffer[buffer_size - 1] != '\n') - { - RRDD_LOG (LOG_INFO, "handle_request: malformed request."); + RRDD_LOG (LOG_ERR, "handle_request: sread failed."); return (-1); } - - /* Accept Windows style line endings, too */ - if ((buffer_size > 2) && (buffer[buffer_size - 2] == '\r')) - { - buffer_size--; - buffer[buffer_size - 1] = '\n'; - } + buffer_size = (size_t) status; + assert (buffer_size <= sizeof (buffer)); + assert (buffer[buffer_size - 1] == 0); /* Place the normal field separator at the end to simplify * `buffer_get_field's work. */ @@ -979,10 +1046,10 @@ static int handle_request (int fd) /* {{{ */ snprintf (result, sizeof (result), "-1 Unknown command: %s\n", command); result[sizeof (result) - 1] = 0; - status = write (fd, result, strlen (result)); + status = swrite (fd, result, strlen (result)); if (status < 0) { - RRDD_LOG (LOG_ERR, "handle_request: write(2) failed."); + RRDD_LOG (LOG_ERR, "handle_request: swrite failed."); return (-1); } }