From: Florian Forster Date: Sat, 23 Feb 2008 11:05:40 +0000 (+0100) Subject: src/utils_tail.[ch]: Streamlined error handling. X-Git-Tag: collectd-4.4.0~92^2 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=500d52e468127c04c7fb6dffd8239e630b37160d;p=collectd.git src/utils_tail.[ch]: Streamlined error handling. Also the coding style has been adapted to match the one of the rest of the daemon better. --- diff --git a/src/utils_tail.c b/src/utils_tail.c index 5e5aa03d..2ac478f0 100644 --- a/src/utils_tail.c +++ b/src/utils_tail.c @@ -1,6 +1,6 @@ /** * collectd - src/utils_tail.c - * Copyright (C) 2008 C-Ware, Inc. + * Copyright (C) 2007-2008 C-Ware, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -23,12 +23,9 @@ * the end of a file. **/ - +#include "collectd.h" +#include "common.h" #include "utils_tail.h" -#include -#include -#include -#include struct cu_tail_s { @@ -71,26 +68,45 @@ int cu_tail_destroy (cu_tail_t *obj) int cu_tail_readline (cu_tail_t *obj, char *buf, int buflen) { struct stat stat_now; - FILE *new_fd; - int len; + int status; - if( buflen < 1 ) - return -1; + if (buflen < 1) + return (-1); - *buf = '\0'; - if (stat (obj->file, &stat_now) != 0) - return 0; + { + char errbuf[1024]; + ERROR ("cu_tail_readline: stat (%s) failed: %s", + obj->file, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } - if (stat_now.st_dev != obj->stat.st_dev || - stat_now.st_ino != obj->stat.st_ino) + if ((stat_now.st_dev != obj->stat.st_dev) || + (stat_now.st_ino != obj->stat.st_ino)) { + /* + * If the file was replaced open the new file and close the + * old filehandle + */ + FILE *new_fd; + new_fd = fopen (obj->file, "r"); if (new_fd == NULL) - return -1; + { + char errbuf[1024]; + ERROR ("cu_tail_readline: open (%s) failed: %s", + obj->file, + sstrerror (errno, errbuf, + sizeof (errbuf))); + return (-1); + } + /* If there was no previous file, seek to the end. We don't + * want to read in the entire file, usually. */ if (obj->stat.st_ino == 0) fseek (new_fd, 0, SEEK_END); + if (obj->fd != NULL) fclose (obj->fd); obj->fd = new_fd; @@ -98,32 +114,44 @@ int cu_tail_readline (cu_tail_t *obj, char *buf, int buflen) } else if (stat_now.st_size < obj->stat.st_size) { + /* + * Else, if the file was not replaces, but the file was + * truncated, seek to the beginning of the file. + */ + assert (obj->fd != NULL); rewind (obj->fd); } - memcpy (&obj->stat, &stat_now, sizeof (struct stat)); - - if (fgets (buf, buflen, obj->fd) == NULL && feof (obj->fd) == 0) - return -1; - - len = strlen (buf); - if (len > 0 && *(buf + len - 1) != '\n' && feof (obj->fd)) + status = 0; + if (fgets (buf, buflen, obj->fd) == NULL) { - fseek (obj->fd, -len, SEEK_CUR); - *buf = '\0'; + if (feof (obj->fd) == 0) + buf[0] = '\0'; + else /* an error occurred */ + status = -1; } - return 0; + if (status == 0) + memcpy (&obj->stat, &stat_now, sizeof (struct stat)); + + return (status); } /* int cu_tail_readline */ -int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc *func, void *data) +int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc *callback, + void *data) { - int ret; + int status; + + while ((status = cu_tail_readline (obj, buf, buflen)) == 0) + { + /* check for EOF */ + if (buf[0] == '\0') + break; - while ((ret = cu_tail_readline (obj, buf, buflen)) == 0) - if (*buf == '\0' || (ret = func (data, buf, buflen))) - break; + status = callback (data, buf, buflen); + if (status != 0) + break; + } - return ret; + return status; } /* int cu_tail_read */ - diff --git a/src/utils_tail.h b/src/utils_tail.h index a456870c..9535dae4 100644 --- a/src/utils_tail.h +++ b/src/utils_tail.h @@ -1,6 +1,6 @@ /** * collectd - src/utils_tail.h - * Copyright (C) 2007 C-Ware, Inc. + * Copyright (C) 2007-2008 C-Ware, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -59,7 +59,12 @@ int cu_tail_destroy (cu_tail_t *obj); * * Reads from the file until `buflen' characters are read, a newline * character is read, or an eof condition is encountered. `buf' is - * always null-terminated on successful return. + * always null-terminated on successful return and isn't touched when non-zero + * is returned. + * + * You can check if the EOF condition is reached by looking at the buffer: If + * the length of the string stored in the buffer is zero, EOF occurred. + * Otherwise at least the newline character will be in the buffer. * * Returns 0 when successful and non-zero otherwise. */ @@ -72,6 +77,7 @@ int cu_tail_readline (cu_tail_t *obj, char *buf, int buflen); * * Returns 0 when successful and non-zero otherwise. */ -int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc *func, void *data); +int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc *callback, + void *data); #endif /* UTILS_TAIL_H */