6794f8f834ec038513ec2d642a89c485d025a2d9
[ossec-hids.git] / src / shared / store_op.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  */
11
12 /* Common API for dealing with ordered lists.
13  * Provides a fast search on average (n/2).
14  */ 
15
16
17 #include "shared.h"
18
19
20 /* Create the list storage 
21  * Return NULL on error
22  */
23 OSStore *OSStore_Create()
24 {
25     OSStore *my_list;
26
27     my_list = calloc(1, sizeof(OSStore));
28     if(!my_list)
29         return(NULL);
30     
31     my_list->first_node = NULL;
32     my_list->last_node = NULL;
33     my_list->cur_node = NULL;
34     my_list->currently_size = 0;
35     my_list->max_size = 0;
36     my_list->free_data_function = NULL;
37     
38     return(my_list);
39 }
40
41
42
43 /* Deletes the list storage 
44  * Return NULL on error
45  */
46 OSStore *OSStore_Free(OSStore *list)
47 {
48     OSStoreNode *delnode;
49     list->cur_node = list->first_node;
50
51     while(list->cur_node)
52     {
53         if(list->cur_node->key)
54         {
55             free(list->cur_node->key);
56             list->cur_node->key = NULL;
57         }
58         if(list->cur_node->data)
59         {
60             free(list->cur_node->data);
61             list->cur_node->data = NULL;
62         }
63
64         /* Deleting each node. */
65         delnode = list->cur_node;
66         list->cur_node = list->cur_node->next;
67         free(delnode);
68     }
69
70     list->first_node = NULL;
71     list->last_node = NULL;
72
73     free(list);
74     list = NULL;
75     
76     return(list);
77 }
78
79
80
81 /* Set the maximum number of elements
82  * in the storage. Returns 0 on error or
83  * 1 on success.
84  */
85 int OSStore_SetMaxSize(OSStore *list, int max_size)
86 {
87     if(!list)
88     {
89         return(0);
90     }
91     
92     /* Minimum size is 1 */
93     if(max_size <= 1)
94     {
95         return(0);
96     }
97
98     list->max_size = max_size;
99
100     return(1);
101 }
102
103
104
105 /* Set the pointer to the function to free the memory
106  * data.
107  */
108 int OSStore_SetFreeDataPointer(OSStore *list, void *free_data_function)
109 {
110     if(!list)
111     {
112         return(0);
113     }
114     
115     list->free_data_function = free_data_function;
116     return(1);
117 }
118
119
120
121 /* Sorts the storage by size.
122  *
123  */
124 int OSStore_Sort(OSStore *list, void*(sort_data_function)(void *d1, void *d2))
125 {
126     OSStoreNode *newnode = NULL;
127     OSStoreNode *movenode = NULL;
128     list->cur_node = list->first_node;
129
130     while(list->cur_node)
131     {
132         movenode = list->cur_node->prev;
133
134         /* Here we check for all the previous entries, using the sort . */
135         while(movenode)
136         {
137
138             if(sort_data_function(list->cur_node->data, movenode->data))
139             {
140                 movenode = movenode->prev;
141             }
142
143             /* In here, this node should stay where it is. */
144             else if(movenode == list->cur_node->prev)
145             {
146                 break;   
147             }
148
149             /* In here we need to replace the nodes. */
150             else
151             {
152                 newnode = list->cur_node;
153                 
154                 if(list->cur_node->prev)
155                     list->cur_node->prev->next = list->cur_node->next;
156                         
157                 if(list->cur_node->next)
158                     list->cur_node->next->prev = list->cur_node->prev;
159                 else
160                     list->last_node = list->cur_node->prev;    
161                 
162                 list->cur_node = list->cur_node->prev;       
163
164                 
165                 newnode->next = movenode->next;
166                 newnode->prev = movenode;
167
168                 if(movenode->next)
169                     movenode->next->prev = newnode;
170                     
171                 movenode->next = newnode;
172
173                 
174                 break;
175             }
176         }
177
178
179         /* If movenode is not set, we need to put the current node in first.*/
180         if(!movenode && (list->cur_node != list->first_node))
181         {
182             newnode = list->cur_node;
183
184             if(list->cur_node->prev)
185                 list->cur_node->prev->next = list->cur_node->next;
186             
187             if(list->cur_node->next)
188                 list->cur_node->next->prev = list->cur_node->prev;
189             else    
190                 list->last_node = list->cur_node->prev;    
191             
192             list->cur_node = list->cur_node->prev;
193             
194             newnode->prev = NULL;
195             newnode->next = list->first_node;
196             list->first_node->prev = newnode;
197             
198             list->first_node = newnode;    
199         }
200         
201         list->cur_node = list->cur_node->next;
202     }
203
204     return(1);
205 }
206
207
208
209 /* Get key position from storage
210  * Returns 0 if not present or the key
211  * if available.
212  * (position may change after each PUT)
213  */
214 int OSStore_GetPosition(OSStore *list, char *key)
215 {
216     int chk_rc, pos = 1;
217     list->cur_node = list->first_node;
218
219     while(list->cur_node)
220     {
221         if((chk_rc = strcmp(list->cur_node->key, key)) >= 0)
222         {
223             /* Found */
224             if(chk_rc == 0)
225                 return(pos);
226
227             /* Not found */
228             return(0);
229         }
230
231         list->cur_node = list->cur_node->next;
232         pos++;
233     }
234     return(0);
235 }
236
237
238
239 /* Get first node from storage.
240  * Returns NULL if not present.
241  */
242 OSStoreNode *OSStore_GetFirstNode(OSStore *list)
243 {
244     return(list->first_node);
245 }
246
247
248
249 /* Get data from storage.
250  * Returns NULL if not present.
251  */
252 void *OSStore_Get(OSStore *list, char *key)
253 {
254     int chk_rc;
255     list->cur_node = list->first_node;
256     
257     while(list->cur_node)
258     {
259         if((chk_rc = strcmp(list->cur_node->key, key)) >= 0)
260         {
261             /* Found */
262             if(chk_rc == 0)
263                 return(list->cur_node->data);
264
265             /* Not found */    
266             return(NULL);
267         }
268
269         list->cur_node = list->cur_node->next;
270     }
271     return(NULL);
272 }
273
274
275
276 /* Check if key is present on storage.
277  * Returns 0 if not present.
278  */
279 int OSStore_Check(OSStore *list, char *key)
280 {
281     int chk_rc;
282     list->cur_node = list->first_node;
283     
284     while(list->cur_node)
285     {
286         if((chk_rc = strcmp(list->cur_node->key, key)) >= 0)
287         {
288             /* Found */
289             if(chk_rc == 0)
290                 return(1);
291
292             /* Not found */    
293             return(0);
294         }
295
296         list->cur_node = list->cur_node->next;
297     }
298     return(0);
299 }
300
301
302
303 /* Check if key is present on storage (using strncmp).
304  * Returns 0 if not present.
305  */
306 int OSStore_NCheck(OSStore *list, char *key)
307 {
308     int chk_rc;
309     list->cur_node = list->first_node;
310
311     while(list->cur_node)
312     {
313         if((chk_rc = strncmp(list->cur_node->key, key, 
314                              list->cur_node->key_size)) >= 0)
315         {
316             /* Found */
317             if(chk_rc == 0)
318                 return(1);
319
320             /* Not found */
321             return(0);
322         }
323
324         list->cur_node = list->cur_node->next;
325     }
326     return(0);
327 }
328
329
330
331 /* Check if key is present on storage (case insensitive).
332  * Returns 0 if not present.
333  */
334 int OSStore_NCaseCheck(OSStore *list, char *key)
335 {
336     int chk_rc;
337     list->cur_node = list->first_node;
338
339     while(list->cur_node)
340     {
341         if((chk_rc = strncasecmp(list->cur_node->key, key,
342                                  list->cur_node->key_size)) == 0)
343         {
344             return(1);
345         }
346
347         list->cur_node = list->cur_node->next;
348     }
349     return(0);
350 }
351
352
353
354 /* Delete this node from list
355  * Pointer goes to the next node available.
356  */
357 void OSStore_Delete(OSStore *list, char *key)
358 {
359     return;
360 }
361
362
363
364 /* Add data to the list
365  * Returns 1 on success and 0 on failure
366  */
367 int OSStore_Put(OSStore *list, char *key, void *data)
368 {
369     int chk_rc;
370     OSStoreNode *newnode;    
371
372
373     /* Allocating memory for new node */
374     newnode = calloc(1, sizeof(OSStoreNode));
375     if(!newnode)
376     {
377         merror(MEM_ERROR, __local_name);
378         return(0);
379     }
380
381     newnode->prev = NULL;
382     newnode->next = NULL;
383     newnode->data = data;
384     newnode->key = key;
385     newnode->key_size = strlen(key);
386
387
388     /* If we don't have first node, assign it */
389     if(!list->first_node)
390     {
391         list->first_node = newnode;
392         list->last_node = newnode;
393     }
394     
395  
396     /* Store the data in order */ 
397     else
398     {
399         list->cur_node = list->first_node;
400         while(list->cur_node)
401         {
402             if((chk_rc = strcmp(list->cur_node->key, key)) >= 0)
403             {
404                 /* Duplicated entry */
405                 if(chk_rc == 0)
406                 {
407                     return(1);
408                 }
409                 
410                 /* If there is no prev node, it is because
411                  * this is the first node. 
412                  */
413                 if(list->cur_node->prev)
414                     list->cur_node->prev->next = newnode;
415                 else
416                     list->first_node = newnode;
417                                             
418                 
419                 newnode->prev = list->cur_node->prev;
420                 
421                 list->cur_node->prev = newnode;
422                 newnode->next = list->cur_node;
423                 break;
424             }
425
426             list->cur_node = list->cur_node->next;
427         }
428
429         /* New node is the higher key */
430         if(!newnode->next)
431         {
432             list->last_node->next = newnode;
433             newnode->prev = list->last_node;
434             list->last_node = newnode;
435         }
436     }
437     
438
439     /* Increment list size */
440     list->currently_size++;
441     
442     return(1);
443 }
444
445 /* EOF */