| |
1 /* |
| |
2 * nmfield.c |
| |
3 * |
| |
4 * Copyright (c) 2004 Novell, Inc. All Rights Reserved. |
| |
5 * |
| |
6 * This program is free software; you can redistribute it and/or modify |
| |
7 * it under the terms of the GNU General Public License as published by |
| |
8 * the Free Software Foundation; version 2 of the License. |
| |
9 * |
| |
10 * This program is distributed in the hope that it will be useful, |
| |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| |
13 * GNU General Public License for more details. |
| |
14 * |
| |
15 * You should have received a copy of the GNU General Public License |
| |
16 * along with this program; if not, write to the Free Software |
| |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
18 * |
| |
19 */ |
| |
20 |
| |
21 #include <string.h> |
| |
22 #include <stdio.h> |
| |
23 #include "nmfield.h" |
| |
24 |
| |
25 /* Free a field value and tag */ |
| |
26 static void _free_field(NMField * field); |
| |
27 |
| |
28 /* Free a field value */ |
| |
29 static void _free_field_value(NMField * field); |
| |
30 |
| |
31 /* Make a deep copy of the field */ |
| |
32 static void _copy_field(NMField * dest, NMField * src); |
| |
33 |
| |
34 /* Make a deep copy of the field's value */ |
| |
35 static void _copy_field_value(NMField * dest, NMField * src); |
| |
36 |
| |
37 /* Create a string from a value -- for debugging */ |
| |
38 static char *_value_to_string(NMField * field); |
| |
39 |
| |
40 static NMField * |
| |
41 _add_blank_field(NMField *fields, guint32 count) |
| |
42 { |
| |
43 guint32 new_len; |
| |
44 |
| |
45 if (fields == NULL) { |
| |
46 fields = g_new0(NMField, 10); |
| |
47 fields->len = 10; |
| |
48 } else { |
| |
49 if (fields->len < count + 2) { |
| |
50 new_len = count + 10; |
| |
51 fields = g_realloc(fields, new_len * sizeof(NMField)); |
| |
52 fields->len = new_len; |
| |
53 } |
| |
54 } |
| |
55 return fields; |
| |
56 } |
| |
57 |
| |
58 NMField * |
| |
59 nm_field_add_number(NMField * fields, const char *tag, guint32 size, guint8 method, |
| |
60 guint8 flags, guint32 value, guint8 type) |
| |
61 { |
| |
62 guint32 count; |
| |
63 NMField *field; |
| |
64 |
| |
65 count = nm_count_fields(fields); |
| |
66 fields = _add_blank_field(fields, count); |
| |
67 |
| |
68 field = &(fields[count]); |
| |
69 field->tag = g_strdup(tag); |
| |
70 field->size = size; |
| |
71 field->method = method; |
| |
72 field->flags = flags; |
| |
73 field->value = value; |
| |
74 field->type = type; |
| |
75 |
| |
76 /* Null terminate the field array */ |
| |
77 field = &((fields)[count + 1]); |
| |
78 field->tag = NULL; |
| |
79 field->value = 0; |
| |
80 field->ptr_value = NULL; |
| |
81 |
| |
82 return fields; |
| |
83 } |
| |
84 |
| |
85 NMField * |
| |
86 nm_field_add_pointer(NMField * fields, const char *tag, guint32 size, guint8 method, |
| |
87 guint8 flags, gpointer value, guint8 type) |
| |
88 { |
| |
89 guint32 count; |
| |
90 NMField *field = NULL; |
| |
91 |
| |
92 count = nm_count_fields(fields); |
| |
93 fields = _add_blank_field(fields, count); |
| |
94 |
| |
95 field = &(fields[count]); |
| |
96 field->tag = g_strdup(tag); |
| |
97 field->size = size; |
| |
98 field->method = method; |
| |
99 field->flags = flags; |
| |
100 field->ptr_value = value; |
| |
101 field->type = type; |
| |
102 |
| |
103 /* Null terminate the field array */ |
| |
104 field = &((fields)[count + 1]); |
| |
105 field->tag = NULL; |
| |
106 field->value = 0; |
| |
107 field->ptr_value = NULL; |
| |
108 |
| |
109 return fields; |
| |
110 } |
| |
111 |
| |
112 guint32 |
| |
113 nm_count_fields(NMField * fields) |
| |
114 { |
| |
115 guint32 count = 0; |
| |
116 |
| |
117 if (fields) { |
| |
118 while (fields->tag != NULL) { |
| |
119 count++; |
| |
120 fields++; |
| |
121 } |
| |
122 } |
| |
123 |
| |
124 return count; |
| |
125 } |
| |
126 |
| |
127 void |
| |
128 nm_free_fields(NMField ** fields) |
| |
129 { |
| |
130 NMField *field = NULL; |
| |
131 |
| |
132 if ((fields == NULL) || (*fields == NULL)) |
| |
133 return; |
| |
134 |
| |
135 field = *fields; |
| |
136 |
| |
137 while (field->tag != NULL) { |
| |
138 _free_field(field); |
| |
139 field++; |
| |
140 } |
| |
141 |
| |
142 g_free(*fields); |
| |
143 *fields = NULL; |
| |
144 } |
| |
145 |
| |
146 |
| |
147 static void |
| |
148 _free_field(NMField * field) |
| |
149 { |
| |
150 if (field == NULL) |
| |
151 return; |
| |
152 |
| |
153 _free_field_value(field); |
| |
154 g_free(field->tag); |
| |
155 } |
| |
156 |
| |
157 static void |
| |
158 _free_field_value(NMField * field) |
| |
159 { |
| |
160 if (field == NULL) |
| |
161 return; |
| |
162 |
| |
163 switch (field->type) { |
| |
164 case NMFIELD_TYPE_BINARY: |
| |
165 case NMFIELD_TYPE_UTF8: |
| |
166 case NMFIELD_TYPE_DN: |
| |
167 if (field->ptr_value != NULL) { |
| |
168 g_free(field->ptr_value); |
| |
169 } |
| |
170 break; |
| |
171 |
| |
172 case NMFIELD_TYPE_ARRAY: |
| |
173 case NMFIELD_TYPE_MV: |
| |
174 nm_free_fields((NMField **)&field->ptr_value); |
| |
175 break; |
| |
176 |
| |
177 default: |
| |
178 break; |
| |
179 } |
| |
180 |
| |
181 field->size = 0; |
| |
182 field->ptr_value = NULL; |
| |
183 } |
| |
184 |
| |
185 NMField * |
| |
186 nm_locate_field(char *tag, NMField * fields) |
| |
187 { |
| |
188 NMField *ret_fields = NULL; |
| |
189 |
| |
190 if ((fields == NULL) || (tag == NULL)) { |
| |
191 return NULL; |
| |
192 } |
| |
193 |
| |
194 while (fields->tag != NULL) { |
| |
195 if (g_ascii_strcasecmp(fields->tag, tag) == 0) { |
| |
196 ret_fields = fields; |
| |
197 break; |
| |
198 } |
| |
199 fields++; |
| |
200 } |
| |
201 |
| |
202 return ret_fields; |
| |
203 } |
| |
204 |
| |
205 NMField * |
| |
206 nm_copy_field_array(NMField * src) |
| |
207 { |
| |
208 NMField *ptr = NULL; |
| |
209 NMField *dest = NULL; |
| |
210 int count; |
| |
211 |
| |
212 if (src != NULL) { |
| |
213 count = nm_count_fields(src) + 1; |
| |
214 dest = g_new0(NMField, count); |
| |
215 dest->len = count; |
| |
216 ptr = dest; |
| |
217 while (src->tag != NULL) { |
| |
218 _copy_field(ptr, src); |
| |
219 ptr++; |
| |
220 src++; |
| |
221 } |
| |
222 } |
| |
223 |
| |
224 return dest; |
| |
225 } |
| |
226 |
| |
227 static void |
| |
228 _copy_field(NMField * dest, NMField * src) |
| |
229 { |
| |
230 dest->type = src->type; |
| |
231 dest->flags = src->flags; |
| |
232 dest->method = src->method; |
| |
233 dest->tag = g_strdup(src->tag); |
| |
234 _copy_field_value(dest, src); |
| |
235 } |
| |
236 |
| |
237 static void |
| |
238 _copy_field_value(NMField * dest, NMField * src) |
| |
239 { |
| |
240 dest->type = src->type; |
| |
241 switch (dest->type) { |
| |
242 case NMFIELD_TYPE_UTF8: |
| |
243 case NMFIELD_TYPE_DN: |
| |
244 if (src->size == 0 && src->ptr_value != NULL) { |
| |
245 src->size = strlen((char *) src->ptr_value) + 1; |
| |
246 } |
| |
247 /* fall through */ |
| |
248 case NMFIELD_TYPE_BINARY: |
| |
249 if (src->size != 0 && src->ptr_value != NULL) { |
| |
250 dest->ptr_value = g_new0(char, src->size); |
| |
251 memcpy(dest->ptr_value, src->ptr_value, src->size); |
| |
252 } |
| |
253 break; |
| |
254 |
| |
255 case NMFIELD_TYPE_ARRAY: |
| |
256 case NMFIELD_TYPE_MV: |
| |
257 dest->ptr_value = nm_copy_field_array((NMField *)src->ptr_value); |
| |
258 break; |
| |
259 |
| |
260 default: |
| |
261 /* numeric value */ |
| |
262 dest->value = src->value; |
| |
263 break; |
| |
264 } |
| |
265 |
| |
266 dest->size = src->size; |
| |
267 } |
| |
268 |
| |
269 void |
| |
270 nm_remove_field(NMField * field) |
| |
271 { |
| |
272 NMField *tmp; |
| |
273 guint32 len; |
| |
274 |
| |
275 if ((field != NULL) && (field->tag != NULL)) { |
| |
276 _free_field(field); |
| |
277 |
| |
278 /* Move fields down */ |
| |
279 tmp = field + 1; |
| |
280 while (1) { |
| |
281 /* Don't overwrite the size of the array */ |
| |
282 len = field->len; |
| |
283 |
| |
284 *field = *tmp; |
| |
285 |
| |
286 field->len = len; |
| |
287 |
| |
288 if (tmp->tag == NULL) |
| |
289 break; |
| |
290 |
| |
291 field++; |
| |
292 tmp++; |
| |
293 } |
| |
294 } |
| |
295 } |
| |
296 |
| |
297 void |
| |
298 nm_print_fields(NMField * fields) |
| |
299 { |
| |
300 char *str = NULL; |
| |
301 NMField *field = fields; |
| |
302 |
| |
303 if (fields == NULL) |
| |
304 return; |
| |
305 |
| |
306 while (field->tag != NULL) { |
| |
307 if (field->type == NMFIELD_TYPE_ARRAY || field->type == NMFIELD_TYPE_MV) { |
| |
308 printf("Subarray START: %s Method = %d\n", field->tag, field->method); |
| |
309 nm_print_fields((NMField *) field->ptr_value); |
| |
310 printf("Subarray END: %s\n", field->tag); |
| |
311 } else { |
| |
312 str = _value_to_string(field); |
| |
313 printf("Tag=%s;Value=%s\n", field->tag, str); |
| |
314 g_free(str); |
| |
315 str = NULL; |
| |
316 } |
| |
317 field++; |
| |
318 } |
| |
319 |
| |
320 } |
| |
321 |
| |
322 static char * |
| |
323 _value_to_string(NMField * field) |
| |
324 { |
| |
325 char *value = NULL; |
| |
326 |
| |
327 if (field == NULL) |
| |
328 return NULL; |
| |
329 |
| |
330 /* This is a single value attribute */ |
| |
331 if (((field->type == NMFIELD_TYPE_UTF8) || |
| |
332 (field->type == NMFIELD_TYPE_DN)) && (field->ptr_value != NULL)) { |
| |
333 value = g_strdup((const char *) field->ptr_value); |
| |
334 } else if (field->type == NMFIELD_TYPE_BINARY && field->ptr_value != NULL) { |
| |
335 value = g_new0(char, field->size); |
| |
336 memcpy(value, (const char *) field->ptr_value, field->size); |
| |
337 } else if (field->type == NMFIELD_TYPE_BOOL) { |
| |
338 if (field->value) { |
| |
339 value = g_strdup(NM_FIELD_TRUE); |
| |
340 } else { |
| |
341 value = g_strdup(NM_FIELD_FALSE); |
| |
342 } |
| |
343 } else { |
| |
344 /* assume it is a number */ |
| |
345 value = g_new0(char, 20); |
| |
346 |
| |
347 switch (field->type) { |
| |
348 case NMFIELD_TYPE_BYTE: |
| |
349 case NMFIELD_TYPE_WORD: |
| |
350 case NMFIELD_TYPE_DWORD: |
| |
351 value = g_strdup_printf("%ld", (long) field->value); |
| |
352 break; |
| |
353 |
| |
354 case NMFIELD_TYPE_UBYTE: |
| |
355 case NMFIELD_TYPE_UWORD: |
| |
356 case NMFIELD_TYPE_UDWORD: |
| |
357 value = g_strdup_printf("%lu", (unsigned long) field->value); |
| |
358 break; |
| |
359 } |
| |
360 } |
| |
361 |
| |
362 if (value == NULL) |
| |
363 value = g_strdup("NULL"); |
| |
364 |
| |
365 return value; |
| |
366 } |