Imported Upstream version 2.7
[ossec-hids.git] / src / shared / dirtree_op.c
1 /* @(#) $Id: ./src/shared/dirtree_op.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All rights reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation.
11  *
12  * License details at the LICENSE file included with OSSEC or
13  * online at: http://www.ossec.net/en/licensing.html
14  */
15
16
17 /* Common API for dealing with directory trees */
18
19
20 #include "shared.h"
21
22
23 /* Create the tree
24  * Return NULL on error
25  */
26 OSDirTree *OSDirTree_Create()
27 {
28     OSDirTree *my_tree;
29
30     my_tree = calloc(1, sizeof(OSDirTree));
31     if(!my_tree)
32     {
33         return(NULL);
34     }
35
36     my_tree->first_node = NULL;
37     my_tree->last_node = NULL;
38
39     return(my_tree);
40 }
41
42
43
44 /* Get first node from tree (starting from parent)
45  * Returns null on invalid tree (not initialized)
46  */
47 OSTreeNode *OSDirTree_GetFirstNode(OSDirTree *tree)
48 {
49     return(tree->first_node);
50 }
51
52
53
54 /** OSDirTree *_OSTreeNode_Add
55  * Internal call, looks up for an entry in the middle of the tree.
56  * Should not be called directly.
57  */
58 OSDirTree *_OSTreeNode_Add(OSDirTree *tree, char *str,
59                            void *data, char sep)
60 {
61     char *tmp_str;
62     OSTreeNode *newnode;
63     OSTreeNode *curnode;
64
65
66     /* Looking for a next entry */
67     tmp_str = strchr(str, sep);
68     if(tmp_str)
69     {
70         *tmp_str = '\0';
71     }
72
73
74     /* Creating new tree */
75     if(!tree)
76     {
77         tree = calloc(1, sizeof(OSDirTree));
78         if(!tree)
79         {
80             return(NULL);
81         }
82
83         tree->first_node = NULL;
84         tree->last_node = NULL;
85     }
86
87
88     curnode = tree->first_node;
89
90     /* Looping on all nodes */
91     while(curnode)
92     {
93         if(strcmp(curnode->value, str) == 0)
94         {
95             /* If we have other elements, keep going */
96             if(tmp_str)
97             {
98                 curnode->child = _OSTreeNode_Add(curnode->child,
99                                                  tmp_str +1, data, sep);
100             }
101             break;
102         }
103         curnode = curnode->next;
104     }
105
106
107     /* Add a new entry, if not found. */
108     if(!curnode)
109     {
110         os_calloc(1, sizeof(OSTreeNode), newnode);
111         //printf("XXXX Adding node: %s\n", str);
112
113
114         if(!tree->first_node && !tree->last_node)
115         {
116             tree->last_node = newnode;
117             tree->first_node = newnode;
118         }
119         else
120         {
121             tree->last_node->next = newnode;
122         }
123
124         newnode->next = NULL;
125         tree->last_node = newnode;
126         os_strdup(str, newnode->value);
127
128
129         /* If we have other elements, keep going */
130         if(tmp_str)
131         {
132             newnode->child = _OSTreeNode_Add(newnode->child,
133                     tmp_str +1, data, sep);
134             newnode->data = NULL;
135         }
136         /* Otherwise, set the data in here */
137         else
138         {
139             newnode->data = data;
140             newnode->child = NULL;
141         }
142     }
143
144
145     /* Fixing the string back */
146     if(tmp_str)
147     {
148         *tmp_str = sep;
149     }
150
151
152     return(tree);
153 }
154
155
156
157 /** void OSDirTree_AddToTree
158  * Adds a new string to the tree, setting the data at the final leaf.
159  * The tree will be divided by the "separator", where each token
160  * will delimiter the child.
161  * For example, /etc/my/name.conf will become:
162  *              /etc/
163  *                   -> /my
164  *                        -> /name.conf
165  * Str must not be NULL.
166  */
167 void OSDirTree_AddToTree(OSDirTree *tree, char *str, void *data, char sep)
168 {
169     char *tmp_str;
170     OSTreeNode *newnode;
171     OSTreeNode *curnode;
172
173
174     /* First character doesn't count as a separator */
175     tmp_str = strchr(str +1, sep);
176     if(tmp_str)
177     {
178         *tmp_str = '\0';
179     }
180
181
182     curnode = tree->first_node;
183     while(curnode)
184     {
185         if(strcmp(str, curnode->value) == 0)
186         {
187             /* If we have other elements, keep going */
188             if(tmp_str)
189             {
190                 curnode->child = _OSTreeNode_Add(curnode->child,
191                                                  tmp_str +1, data, sep);
192             }
193             break;
194         }
195
196         curnode = curnode->next;
197     }
198
199
200     /* If we didn't find an entry, create one. */
201     if(!curnode)
202     {
203         os_calloc(1, sizeof(OSTreeNode), newnode);
204         printf("XX Adding MAIN node: %s\n", str);
205
206         if(!tree->first_node && !tree->last_node)
207         {
208             tree->last_node = newnode;
209             tree->first_node = newnode;
210         }
211         else
212         {
213             printf("XXX last new node: %s\n", tree->last_node->value);
214             tree->last_node->next = newnode;
215             tree->last_node = newnode;
216         }
217
218         newnode->next = NULL;
219         os_strdup(str, newnode->value);
220
221
222         /* If we have other elements, keep going */
223         if(tmp_str)
224         {
225             newnode->child = _OSTreeNode_Add(newnode->child,
226                                              tmp_str +1, data, sep);
227             newnode->data = NULL;
228         }
229         /* Otherwise, set the data in here */
230         else
231         {
232             newnode->data = data;
233             newnode->child = NULL;
234         }
235     }
236
237     /* Fixing the string back */
238     if(tmp_str)
239     {
240         *tmp_str = sep;
241     }
242
243     return;
244 }
245
246
247
248 void *OSDirTree_SearchTree(OSDirTree *tree, char *str, char sep)
249 {
250     void *ret = NULL;
251     char *tmp_str;
252     OSTreeNode *curnode;
253
254
255     /* First character doesn't count as a separator */
256     tmp_str = strchr(str +1, sep);
257     if(tmp_str)
258     {
259         *tmp_str = '\0';
260     }
261
262     printf("looking for: %s\n", str);
263
264     /* If our tree is not empty, look for the main entry */
265     curnode = tree->first_node;
266     while(curnode)
267     {
268         printf("comparing: '%s' and '%s'\n", str, curnode->value);
269         if(strcmp(str, curnode->value) == 0)
270         {
271             printf("found node: %s\n", str);
272
273             /* If we have other elements, keep going */
274             if(tmp_str)
275             {
276                 ret = OSDirTree_SearchTree(curnode->child, tmp_str +1, sep);
277             }
278             else
279             {
280                 ret = curnode->data;
281             }
282             break;
283         }
284
285         curnode = curnode->next;
286     }
287
288
289     /* Fixing the string back */
290     if(tmp_str)
291     {
292         *tmp_str = sep;
293     }
294
295
296     return(ret);
297 }
298
299 /* EOF */