| 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 } |
|