~ubuntu-branches/ubuntu/oneiric/collectd/oneiric

« back to all changes in this revision

Viewing changes to src/utils_tail.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Harl
  • Date: 2008-06-17 10:35:51 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080617103551-9d0ym3zejc7agtt3
Tags: 4.4.1-1
* New upstream release.
  - Fixed another issue of the sensors plugin affecting some chip types
    (Closes: #468143).
  - Fixed creation of "vserver" graphs in collection.cgi (Closes: #475120).
  - Fixed a segfault when using libperl 5.10.
  - collectd now ships libiptc itself.
  New plugins:
  - Ascent server statistics: ascent
  - IPMI sensors information: ipmi
  - PowerDNS name server statistics: powerdns
  - incremental parsing of logfiles: tail
  - TeamSpeak2 server statistics: teamspeak2
  - detailed virtual memory statistics: vmem
* Disable "tcpconns" plugin by default (Closes: #478759).
* Reenabled iptables plugin on all architectures (Closes: #473435).
  - Added the plugin to collectd.conf.
  - Added /usr/share/doc/collectd/examples/iptables/.
  - Added build dependency on linux-libc-dev (>= 2.6.25-4) - that version is
    required because of #479899.
* New debconf template translations:
  - gl.po, thanks to Jacobo Tarrio (Closes: #482667).
* Added a work around for #474087 (broken openipmi .pc files) by forcing the
  inclusion of the ipmi plugin and manually specifying the dependencies.
* Updated standards-version to 3.8.0 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * collectd - src/utils_tail.c
 
3
 * Copyright (C) 2007-2008  C-Ware, Inc.
 
4
 * Copyright (C) 2008  Florian Forster
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; only version 2 of the License is applicable.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
18
 *
 
19
 * Author:
 
20
 *   Luke Heberling <lukeh at c-ware.com>
 
21
 *   Florian Forster <octo at verplant.org>
 
22
 *
 
23
 * Description:
 
24
 *   Encapsulates useful code for plugins which must watch for appends to
 
25
 *   the end of a file.
 
26
 **/
 
27
 
 
28
#include "collectd.h"
 
29
#include "common.h"
 
30
#include "utils_tail.h"
 
31
 
 
32
struct cu_tail_s
 
33
{
 
34
        char  *file;
 
35
        FILE  *fh;
 
36
        struct stat stat;
 
37
};
 
38
 
 
39
static int cu_tail_reopen (cu_tail_t *obj)
 
40
{
 
41
  int seek_end = 0;
 
42
  FILE *fh;
 
43
  struct stat stat_buf;
 
44
  int status;
 
45
 
 
46
  memset (&stat_buf, 0, sizeof (stat_buf));
 
47
  status = stat (obj->file, &stat_buf);
 
48
  if (status != 0)
 
49
  {
 
50
    char errbuf[1024];
 
51
    ERROR ("utils_tail: stat (%s) failed: %s", obj->file,
 
52
        sstrerror (errno, errbuf, sizeof (errbuf)));
 
53
    return (-1);
 
54
  }
 
55
 
 
56
  /* The file is already open.. */
 
57
  if ((obj->fh != NULL) && (stat_buf.st_ino == obj->stat.st_ino))
 
58
  {
 
59
    /* Seek to the beginning if file was truncated */
 
60
    if (stat_buf.st_size < obj->stat.st_size)
 
61
    {
 
62
      INFO ("utils_tail: File `%s' was truncated.", obj->file);
 
63
      status = fseek (obj->fh, 0, SEEK_SET);
 
64
      if (status != 0)
 
65
      {
 
66
        char errbuf[1024];
 
67
        ERROR ("utils_tail: fseek (%s) failed: %s", obj->file,
 
68
            sstrerror (errno, errbuf, sizeof (errbuf)));
 
69
        fclose (obj->fh);
 
70
        obj->fh = NULL;
 
71
        return (-1);
 
72
      }
 
73
    }
 
74
    memcpy (&obj->stat, &stat_buf, sizeof (struct stat));
 
75
    return (1);
 
76
  }
 
77
 
 
78
  /* Seek to the end if we re-open the same file again or the file opened
 
79
   * is the first at all or the first after an error */
 
80
  if ((obj->stat.st_ino == 0) || (obj->stat.st_ino == stat_buf.st_ino))
 
81
    seek_end = 1;
 
82
 
 
83
  fh = fopen (obj->file, "r");
 
84
  if (fh == NULL)
 
85
  {
 
86
    char errbuf[1024];
 
87
    ERROR ("utils_tail: fopen (%s) failed: %s", obj->file,
 
88
        sstrerror (errno, errbuf, sizeof (errbuf)));
 
89
    return (-1);
 
90
  }
 
91
 
 
92
  if (seek_end != 0)
 
93
  {
 
94
    status = fseek (fh, 0, SEEK_END);
 
95
    if (status != 0)
 
96
    {
 
97
      char errbuf[1024];
 
98
      ERROR ("utils_tail: fseek (%s) failed: %s", obj->file,
 
99
          sstrerror (errno, errbuf, sizeof (errbuf)));
 
100
      fclose (fh);
 
101
      return (-1);
 
102
    }
 
103
  }
 
104
 
 
105
  if (obj->fh != NULL)
 
106
    fclose (obj->fh);
 
107
  obj->fh = fh;
 
108
  memcpy (&obj->stat, &stat_buf, sizeof (struct stat));
 
109
 
 
110
  return (0);
 
111
} /* int cu_tail_reopen */
 
112
 
 
113
cu_tail_t *cu_tail_create (const char *file)
 
114
{
 
115
        cu_tail_t *obj;
 
116
 
 
117
        obj = (cu_tail_t *) malloc (sizeof (cu_tail_t));
 
118
        if (obj == NULL)
 
119
                return (NULL);
 
120
        memset (obj, '\0', sizeof (cu_tail_t));
 
121
 
 
122
        obj->file = strdup (file);
 
123
        if (obj->file == NULL)
 
124
        {
 
125
                free (obj);
 
126
                return (NULL);
 
127
        }
 
128
 
 
129
        obj->fh = NULL;
 
130
 
 
131
        return (obj);
 
132
} /* cu_tail_t *cu_tail_create */
 
133
 
 
134
int cu_tail_destroy (cu_tail_t *obj)
 
135
{
 
136
        if (obj->fh != NULL)
 
137
                fclose (obj->fh);
 
138
        free (obj->file);
 
139
        free (obj);
 
140
 
 
141
        return (0);
 
142
} /* int cu_tail_destroy */
 
143
 
 
144
int cu_tail_readline (cu_tail_t *obj, char *buf, int buflen)
 
145
{
 
146
  int status;
 
147
 
 
148
  if (buflen < 1)
 
149
  {
 
150
    ERROR ("utils_tail: cu_tail_readline: buflen too small: %i bytes.",
 
151
        buflen);
 
152
    return (-1);
 
153
  }
 
154
 
 
155
  if (obj->fh == NULL)
 
156
  {
 
157
    status = cu_tail_reopen (obj);
 
158
    if (status < 0)
 
159
      return (status);
 
160
  }
 
161
  assert (obj->fh != NULL);
 
162
 
 
163
  /* Try to read from the filehandle. If that succeeds, everything appears to
 
164
   * be fine and we can return. */
 
165
  if (fgets (buf, buflen, obj->fh) != NULL)
 
166
  {
 
167
    buf[buflen - 1] = 0;
 
168
    return (0);
 
169
  }
 
170
 
 
171
  /* Check if we encountered an error */
 
172
  if (ferror (obj->fh) != 0)
 
173
  {
 
174
    /* Jupp, error. Force `cu_tail_reopen' to reopen the file.. */
 
175
    fclose (obj->fh);
 
176
    obj->fh = NULL;
 
177
  }
 
178
  /* else: eof -> check if the file was moved away and reopen the new file if
 
179
   * so.. */
 
180
 
 
181
  status = cu_tail_reopen (obj);
 
182
  /* error -> return with error */
 
183
  if (status < 0)
 
184
    return (status);
 
185
  /* file end reached and file not reopened -> nothing more to read */
 
186
  else if (status > 0)
 
187
  {
 
188
    buf[0] = 0;
 
189
    return (0);
 
190
  }
 
191
 
 
192
  /* If we get here: file was re-opened and there may be more to read.. Let's
 
193
   * try again. */
 
194
  if (fgets (buf, buflen, obj->fh) != NULL)
 
195
  {
 
196
    buf[buflen - 1] = 0;
 
197
    return (0);
 
198
  }
 
199
 
 
200
  if (ferror (obj->fh) != 0)
 
201
  {
 
202
    char errbuf[1024];
 
203
    WARNING ("utils_tail: fgets (%s) returned an error: %s", obj->file,
 
204
        sstrerror (errno, errbuf, sizeof (errbuf)));
 
205
    fclose (obj->fh);
 
206
    obj->fh = NULL;
 
207
    return (-1);
 
208
  }
 
209
 
 
210
  /* EOf, well, apparently the new file is empty.. */
 
211
  buf[0] = 0;
 
212
  return (0);
 
213
} /* int cu_tail_readline */
 
214
 
 
215
int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc_t *callback,
 
216
                void *data)
 
217
{
 
218
        int status;
 
219
 
 
220
        while (42)
 
221
        {
 
222
                status = cu_tail_readline (obj, buf, buflen);
 
223
                if (status != 0)
 
224
                {
 
225
                        ERROR ("utils_tail: cu_tail_read: cu_tail_readline "
 
226
                                        "failed.");
 
227
                        break;
 
228
                }
 
229
 
 
230
                /* check for EOF */
 
231
                if (buf[0] == 0)
 
232
                        break;
 
233
 
 
234
                status = callback (data, buf, buflen);
 
235
                if (status != 0)
 
236
                {
 
237
                        ERROR ("utils_tail: cu_tail_read: callback returned "
 
238
                                        "status %i.", status);
 
239
                        break;
 
240
                }
 
241
        }
 
242
 
 
243
        return status;
 
244
} /* int cu_tail_read */