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