Makefile: Add target to run sql-dependant tests
[nagios-reports-module.git] / lparse.c
blob6b5ee0ef2c28d21b96be97ca096c32e58a3fd363
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include "lparse.h"
12 static char *buf;
13 #define MAX_BUF ((512 * 1024) - 1)
15 int lparse_fd(int fd, uint size, int (*parse)(char *, uint))
17 uint tot_rd = 0;
19 if (!buf && !(buf = calloc(1, MAX_BUF + 1)))
20 return -1;
22 while (tot_rd < size) {
23 char *next, *cur;
24 int bytes_rd;
25 uint blkparsed;
27 bytes_rd = read(fd, buf, MAX_BUF < size ? MAX_BUF : size);
28 if (bytes_rd < 0)
29 return -1;
31 if (tot_rd + bytes_rd < size) {
32 /* rewind the file to the last found newline */
33 while (buf[bytes_rd - 1] != '\n')
34 bytes_rd--;
35 lseek(fd, tot_rd + bytes_rd, SEEK_SET);
37 tot_rd += bytes_rd;
39 /* set a sentinel for memchr() */
40 buf[bytes_rd] = '\n';
42 cur = buf;
43 for (blkparsed = 0; blkparsed < bytes_rd; cur = next + 1) {
44 uint len;
45 next = memchr(cur, '\n', bytes_rd + 1 - blkparsed);
46 len = next - cur;
47 blkparsed += len + 1;
49 cur[len] = '\0';
50 parse(cur, len);
54 return 0;
57 int lparse_rev_fd(int fd, uint size, int (*parse)(char *, uint))
59 uint tot_rd = 0, parsed = 0, reads = 0, expected_reads = 0;
61 if (!buf && !(buf = calloc(1, MAX_BUF + 1)))
62 return -1;
64 expected_reads = size / MAX_BUF + 1;
65 while (tot_rd < size) {
66 char *cur, *first, *eol, *last;
67 int bytes_rd;
68 uint blkparsed;
69 size_t to_read;
70 off_t pos;
73 * First we figure out where to start reading
74 * and how much to read. Then we lseek() to that
75 * position and actually read it in (works)
77 if (tot_rd + MAX_BUF < size) {
78 to_read = MAX_BUF;
79 } else {
80 to_read = size - tot_rd;
82 pos = lseek(fd, size - tot_rd - to_read, SEEK_SET);
83 reads++;
84 bytes_rd = read(fd, buf, to_read);
85 if (bytes_rd < 0)
86 return -1;
88 if (tot_rd + bytes_rd < size) {
91 * set 'first' to just after first newline or,
92 * failing that, to the start of the buffer itself
94 first = memchr(buf, '\n', bytes_rd);
95 if (!first)
96 first = buf;
97 else
98 first++;
100 /* remember the position of the first found newline */
101 bytes_rd -= first - buf;
102 } else {
103 first = buf;
105 tot_rd += bytes_rd;
108 * if the buffer we just read ends with a newline, we must
109 * discard it from the first round of parsing, or we'll add
110 * one line for each time we read.
112 if (first[bytes_rd - 1] == '\n')
113 --bytes_rd;
115 eol = last = first + bytes_rd;
116 for (blkparsed = 0; blkparsed < bytes_rd; cur = eol - 1) {
117 uint len;
118 char *line;
121 * set 'cur' to first newline befor 'eol', and set
122 * 'line' to first char after it
124 cur = memrchr(first, '\n', bytes_rd - blkparsed);
125 if (!cur) {
126 line = cur = first;
127 } else {
128 line = cur + 1;
131 len = eol - line;
132 blkparsed += len + 1;
134 *eol = '\0';
135 parse(line, len);
136 eol = cur;
138 parsed += bytes_rd;
141 return 0;
144 int lparse_path_real(int rev, const char *path, uint size, int (*parse)(char *, uint))
146 int fd, result;
148 /* zero size files are never interesting */
149 if (!size)
150 return 0;
152 if ((fd = open(path, O_RDONLY)) < 0)
153 return -1;
155 if (rev)
156 result = lparse_rev_fd(fd, size, parse);
157 else
158 result = lparse_fd(fd, size, parse);
160 close(fd);
162 return result;