2 * ausearch-checkpt.c - ausearch checkpointing feature
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "ausearch-checkpt.h"
26 #define DBG 0 /* set to non-zero for debug */
28 /* Remember why we failed */
29 unsigned checkpt_failure = 0;
32 * Remember the file we were processing when we had incomplete events.
33 * We remember this via it's dev and inode
35 static dev_t checkpt_dev = (dev_t)NULL;
36 static ino_t checkpt_ino = (ino_t)NULL;
38 /* Remember the last event output */
39 static event last_event = {0, 0, 0, NULL, 0};
41 /* Loaded values from a given checkpoint file */
42 dev_t chkpt_input_dev = (dev_t)NULL;
43 ino_t chkpt_input_ino = (ino_t)NULL;
44 event chkpt_input_levent = {0, 0, 0, NULL, 0};
47 * Record the dev_t and ino_t of the given file
50 * 1 Failed to get status
53 int set_ChkPtFileDetails(const char *fn)
57 if (stat(fn, &sbuf) != 0) {
58 fprintf(stderr, "Cannot stat audit file for checkpoint "
59 "details - %s: %s\n", fn, strerror(errno));
60 checkpt_failure |= CP_STATFAILED;
63 checkpt_dev = sbuf.st_dev;
64 checkpt_ino = sbuf.st_ino;
70 * Save the given event in the last_event record
75 int set_ChkPtLastEvent(const event *e)
77 /* Set the event node if necessary */
79 if (last_event.node) {
80 if (strcmp(e->node, last_event.node) != 0) {
81 free((void *)last_event.node);
82 last_event.node = strdup(e->node);
85 last_event.node = strdup(e->node);
86 if (last_event.node == NULL) {
87 fprintf(stderr, "No memory to allocate "
88 "checkpoint last event node name\n");
93 free((void *)last_event.node);
94 last_event.node = NULL;
96 last_event.sec = e->sec;
97 last_event.milli = e->milli;
98 last_event.serial = e->serial;
99 last_event.type = e->type;
104 /* Free all checkpoint memory */
105 void free_ChkPtMemory(void)
108 (void)free((void *)last_event.node);
109 last_event.node = NULL;
110 if (chkpt_input_levent.node)
111 (void)free((void *)chkpt_input_levent.node);
112 chkpt_input_levent.node = NULL;
116 * Save the checkpoint to the given file
121 void save_ChkPt(const char *fn)
125 if ((fd = fopen(fn, "w")) == NULL) {
126 fprintf(stderr, "Cannot open checkpoint file - %s: %s\n",
127 fn, strerror(errno));
128 checkpt_failure |= CP_STATUSIO;
131 fprintf(fd, "dev=0x%X\ninode=0x%X\n",
132 (unsigned int)checkpt_dev, (unsigned int)checkpt_ino);
133 fprintf(fd, "output=%s %lu.%03u:%lu 0x%X\n",
134 last_event.node ? last_event.node : "-",
135 (long unsigned int)last_event.sec, last_event.milli,
136 last_event.serial, last_event.type);
141 * Parse a checkpoint file "output=" record
143 * 1 failed to parse or no memory
146 static int parse_checkpt_event(char *lbuf, int ndix, event *e)
151 * Find the space after the node, then make it '\0' so
152 * we terminate the node value. We leave 'rest' at the start
153 * of the event time/serial element
155 rest = strchr(&lbuf[ndix], ' ');
157 fprintf(stderr, "Malformed output/event checkpoint line "
158 "near node - [%s]\n", lbuf);
159 checkpt_failure |= CP_STATUSBAD;
164 if (lbuf[ndix] == '-')
167 e->node = strdup(&lbuf[ndix]);
168 if (e->node == NULL) {
169 fprintf(stderr, "No memory for node when loading "
170 "checkpoint line - [%s]\n", lbuf);
171 checkpt_failure |= CP_NOMEM;
175 if (sscanf(rest, "%lu.%03u:%lu 0x%X", &e->sec, &e->milli,
176 &e->serial, &e->type) != 4) {
177 fprintf(stderr, "Malformed output/event checkpoint line "
178 "after node - [%s]\n", lbuf);
179 checkpt_failure |= CP_STATUSBAD;
187 * Load the checkpoint from the given file
190 * == -1 no file present
193 int load_ChkPt(const char *fn)
199 if ((fd = fopen(fn, "r")) == NULL) {
202 fprintf(stderr, "Cannot open checkpoint file - %s: %s\n",
203 fn, strerror(errno));
206 while (fgets(lbuf, MAX_LN, fd) != NULL) {
207 size_t len = strlen(lbuf);
209 if (len && lbuf[len - 1] == '\n') /* drop the newline */
210 lbuf[len - 1] = '\0';
212 if (strncmp(lbuf, "dev=", 4) == 0) {
214 chkpt_input_dev = strtoul(&lbuf[4], NULL, 16);
216 fprintf(stderr, "Malformed dev checkpoint "
217 "line - [%s]\n", lbuf);
218 checkpt_failure |= CP_STATUSBAD;
221 } else if (strncmp(lbuf, "inode=", 6) == 0) {
223 chkpt_input_ino = strtoul(&lbuf[6], NULL, 16);
225 fprintf(stderr, "Malformed inode checkpoint "
226 "line - [%s]\n", lbuf);
227 checkpt_failure |= CP_STATUSBAD;
230 } else if (strncmp(lbuf, "output=", 7) == 0) {
231 if (parse_checkpt_event(lbuf, 7, &chkpt_input_levent))
234 fprintf(stderr, "Unknown checkpoint line - [%s]\n",
236 checkpt_failure |= CP_STATUSBAD;
240 if ( (chkpt_input_ino == (ino_t)NULL) ||
241 (chkpt_input_dev == (dev_t)NULL) ) {
242 fprintf(stderr, "Missing dev/inode lines from checkpoint "
244 checkpt_failure |= CP_STATUSBAD;
253 fprintf(stderr, "Loaded %s - dev: 0x%X, ino: 0x%X\n",
254 fn, chkpt_input_dev, chkpt_input_ino);
255 fprintf(stderr, "output:%s %d.%03d:%lu 0x%X\n",
256 chkpt_input_levent.node ? chkpt_input_levent.node : "-",
257 chkpt_input_levent.sec, chkpt_input_levent.milli,
258 chkpt_input_levent.serial, chkpt_input_levent.type);