new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / shared / file-queue.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All right reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 /* File monitoring functions */
11
12 #include "shared.h"
13 #include "file-queue.h"
14
15 static void file_sleep(void);
16 static void GetFile_Queue(file_queue *fileq) __attribute__((nonnull));
17 static int Handle_Queue(file_queue *fileq, int flags) __attribute__((nonnull));
18 /* To translate between month (int) to month (char) */
19 static const char *(s_month[]) = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
20                                   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
21                                  };
22
23
24 static void file_sleep()
25 {
26 #ifndef WIN32
27     struct timeval fp_timeout;
28
29     fp_timeout.tv_sec = FQ_TIMEOUT;
30     fp_timeout.tv_usec = 0;
31
32     /* Wait for the select timeout */
33     select(0, NULL, NULL, NULL, &fp_timeout);
34
35 #else
36     /* Windows does not like select that way */
37     Sleep((FQ_TIMEOUT + 2) * 1000);
38 #endif
39
40     return;
41 }
42
43 /* Get the file queue for that specific hour */
44 static void GetFile_Queue(file_queue *fileq)
45 {
46     /* Create the logfile name */
47     fileq->file_name[0] = '\0';
48     fileq->file_name[MAX_FQUEUE] = '\0';
49
50     if (fileq->flags & CRALERT_FP_SET) {
51         snprintf(fileq->file_name, MAX_FQUEUE,
52                  "<stdin>");
53     } else {
54         snprintf(fileq->file_name, MAX_FQUEUE,
55                  "%s/%d/%s/ossec-alerts-%02d.log",
56                  isChroot() ? ALERTS : ALERTS_PATH,
57                  fileq->year,
58                  fileq->mon,
59                  fileq->day);
60     }
61 }
62
63 /* Re Handle the file queue */
64 static int Handle_Queue(file_queue *fileq, int flags)
65 {
66     /* Close if it is open */
67     if (!(flags & CRALERT_FP_SET)) {
68         if (fileq->fp) {
69             fclose(fileq->fp);
70             fileq->fp = NULL;
71         }
72
73         /* We must be able to open the file, fseek and get the
74          * time of change from it.
75          */
76         fileq->fp = fopen(fileq->file_name, "r");
77         if (!fileq->fp) {
78             /* Queue not available */
79             return (0);
80         }
81     }
82
83     /* Seek to the end of the file */
84     if (!(flags & CRALERT_READ_ALL)) {
85         if (fseek(fileq->fp, 0, SEEK_END) < 0) {
86             merror(FSEEK_ERROR, __local_name, fileq->file_name, errno, strerror(errno));
87             if (fileq->fp) {
88                 fclose(fileq->fp);
89                 fileq->fp = NULL;
90             }
91             return (-1);
92         }
93     }
94
95     /* File change time */
96     if (fstat(fileno(fileq->fp), &fileq->f_status) < 0) {
97         merror(FSTAT_ERROR, __local_name, fileq->file_name, errno, strerror(errno));
98         fclose(fileq->fp);
99         fileq->fp = NULL;
100         return (-1);
101     }
102
103     fileq->last_change = fileq->f_status.st_mtime;
104
105     return (1);
106 }
107
108 /* Initiates the file monitoring */
109 int Init_FileQueue(file_queue *fileq, const struct tm *p, int flags)
110 {
111     /* Initialize file_queue fields */
112     if (!(flags & CRALERT_FP_SET)) {
113         fileq->fp = NULL;
114     }
115     fileq->last_change = 0;
116     fileq->flags = 0;
117
118     fileq->day = p->tm_mday;
119     fileq->year = p->tm_year + 1900;
120
121     strncpy(fileq->mon, s_month[p->tm_mon], 3);
122     memset(fileq->file_name, '\0', MAX_FQUEUE + 1);
123
124     /* Set the supplied flags */
125     fileq->flags = flags;
126
127     /* Get latest file */
128     GetFile_Queue(fileq);
129
130     /* Always seek to the end when starting the queue */
131     if (Handle_Queue(fileq, fileq->flags) < 0) {
132         return (-1);
133     }
134
135     return (0);
136 }
137
138 /* Reads from the monitored file */
139 alert_data *Read_FileMon(file_queue *fileq, const struct tm *p, unsigned int timeout)
140 {
141     unsigned int i = 0;
142     alert_data *al_data;
143
144     /* If the file queue is not available, try to access it */
145     if (!fileq->fp) {
146         if (Handle_Queue(fileq, 0) != 1) {
147             file_sleep();
148             return (NULL);
149         }
150     }
151
152     /* Get current file */
153     if (p->tm_mday != fileq->day) {
154         /* If the day changes, get all remaining alerts */
155         al_data = GetAlertData(fileq->flags, fileq->fp);
156         if (!al_data) {
157             fileq->day = p->tm_mday;
158             fileq->year = p->tm_year + 1900;
159             strncpy(fileq->mon, s_month[p->tm_mon], 3);
160
161             /* Get latest file */
162             GetFile_Queue(fileq);
163
164             if (Handle_Queue(fileq, 0) != 1) {
165                 file_sleep();
166                 return (NULL);
167             }
168         } else {
169             return (al_data);
170         }
171     }
172
173     /* Try up to timeout times to get an event */
174     while (i < timeout) {
175         al_data = GetAlertData(fileq->flags, fileq->fp);
176         if (al_data) {
177             return (al_data);
178         }
179
180         i++;
181         file_sleep();
182     }
183
184     /* Return NULL if timeout expires */
185     return (NULL);
186 }