diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2012-06-27 12:24:26 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2012-06-27 12:24:26 +0000 |
commit | f315953dd3ec50b6cf6482834b6403680238d9da (patch) | |
tree | 4d4d5d29d345a1a62772092fc7bb5589ef3e839b /src/util/configuration.c | |
parent | f3e6ce798c7637c4bc66a2ad0496a50f70cc1076 (diff) | |
download | gnunet-f315953dd3ec50b6cf6482834b6403680238d9da.tar.gz gnunet-f315953dd3ec50b6cf6482834b6403680238d9da.zip |
configuration serialization
Diffstat (limited to 'src/util/configuration.c')
-rw-r--r-- | src/util/configuration.c | 155 |
1 files changed, 103 insertions, 52 deletions
diff --git a/src/util/configuration.c b/src/util/configuration.c index 194388fa0..a9697393d 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c | |||
@@ -271,88 +271,139 @@ GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
271 | 271 | ||
272 | 272 | ||
273 | /** | 273 | /** |
274 | * Write configuration file. | 274 | * Serializes the given configuration. |
275 | * | 275 | * |
276 | * @param cfg configuration to write | 276 | * @param cfg configuration to serialize |
277 | * @param filename where to write the configuration | 277 | * @param size will be set to the size of the serialized memory block |
278 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 278 | * @return the memory block where the serialized configuration is |
279 | * present. This memory should be freed by the caller | ||
279 | */ | 280 | */ |
280 | int | 281 | char * |
281 | GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, | 282 | GNUNET_CONFIGURATION_serialize (struct GNUNET_CONFIGURATION_Handle *cfg, |
282 | const char *filename) | 283 | uint16_t *size) |
283 | { | 284 | { |
284 | struct ConfigSection *sec; | 285 | struct ConfigSection *sec; |
285 | struct ConfigEntry *ent; | 286 | struct ConfigEntry *ent; |
286 | FILE *fp; | 287 | char *mem; |
287 | int error; | 288 | char *cbuf; |
288 | char *fn; | ||
289 | char *val; | 289 | char *val; |
290 | char *pos; | 290 | char *pos; |
291 | uint16_t len; | ||
292 | uint16_t m_size; | ||
293 | uint16_t c_size; | ||
291 | 294 | ||
292 | fn = GNUNET_STRINGS_filename_expand (filename); | 295 | |
293 | if (fn == NULL) | 296 | /* Pass1 : calculate the buffer size required */ |
294 | return GNUNET_SYSERR; | 297 | m_size = 0; |
295 | if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) | ||
296 | { | ||
297 | GNUNET_free (fn); | ||
298 | return GNUNET_SYSERR; | ||
299 | } | ||
300 | if (NULL == (fp = FOPEN (fn, "w"))) | ||
301 | { | ||
302 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fopen", fn); | ||
303 | GNUNET_free (fn); | ||
304 | return GNUNET_SYSERR; | ||
305 | } | ||
306 | GNUNET_free (fn); | ||
307 | error = 0; | ||
308 | sec = cfg->sections; | 298 | sec = cfg->sections; |
309 | while (sec != NULL) | 299 | while (NULL != sec) |
310 | { | 300 | { |
311 | if (0 > FPRINTF (fp, "[%s]\n", sec->name)) | 301 | /* For each section we need to add 3 charaters: {'[',']','\n'} */ |
302 | m_size += strlen (sec->name) + 3; | ||
303 | ent = sec->entries; | ||
304 | while (NULL != ent) | ||
312 | { | 305 | { |
313 | error = 1; | 306 | if (NULL != ent->val) |
314 | break; | 307 | { |
308 | /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */ | ||
309 | pos = ent->val; | ||
310 | while (NULL != (pos = strstr (pos, "\n"))) | ||
311 | { | ||
312 | m_size++; | ||
313 | pos++; | ||
314 | } | ||
315 | /* For each key = value pair we need to add 4 characters (2 | ||
316 | spaces and 1 equal-to character and 1 new line) */ | ||
317 | m_size += strlen (ent->key) + strlen (ent->val) + 4; | ||
318 | } | ||
319 | ent = ent->next; | ||
315 | } | 320 | } |
321 | /* A new line after section end */ | ||
322 | m_size++; | ||
323 | sec = sec->next; | ||
324 | } | ||
325 | |||
326 | /* Pass2: Allocate memory and write the configuration to it */ | ||
327 | mem = GNUNET_malloc (m_size); | ||
328 | sec = cfg->sections; | ||
329 | c_size = 0; | ||
330 | *size = c_size; | ||
331 | while (NULL != sec) | ||
332 | { | ||
333 | len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name); | ||
334 | memcpy (mem + c_size, cbuf, len); | ||
335 | c_size += len; | ||
336 | GNUNET_free (cbuf); | ||
316 | ent = sec->entries; | 337 | ent = sec->entries; |
317 | while (ent != NULL) | 338 | while (NULL != ent) |
318 | { | 339 | { |
319 | if (ent->val != NULL) | 340 | if (NULL != ent->val) |
320 | { | 341 | { |
321 | val = GNUNET_malloc (strlen (ent->val) * 2 + 1); | 342 | val = GNUNET_malloc (strlen (ent->val) * 2 + 1); |
322 | strcpy (val, ent->val); | 343 | strcpy (val, ent->val); |
323 | while (NULL != (pos = strstr (val, "\n"))) | 344 | while (NULL != (pos = strstr (val, "\n"))) |
324 | { | 345 | { |
325 | memmove (&pos[2], &pos[1], strlen (&pos[1])); | 346 | memmove (&pos[2], &pos[1], strlen (&pos[1])); |
326 | pos[0] = '\\'; | 347 | pos[0] = '\\'; |
327 | pos[1] = 'n'; | 348 | pos[1] = 'n'; |
328 | } | 349 | } |
329 | if (0 > FPRINTF (fp, "%s = %s\n", ent->key, val)) | 350 | len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val); |
330 | { | 351 | GNUNET_free (val); |
331 | error = 1; | 352 | memcpy (mem + c_size, cbuf, len); |
332 | GNUNET_free (val); | 353 | c_size += len; |
333 | break; | 354 | GNUNET_free (cbuf); |
334 | } | ||
335 | GNUNET_free (val); | ||
336 | } | 355 | } |
337 | ent = ent->next; | 356 | ent = ent->next; |
338 | } | 357 | } |
339 | if (error != 0) | 358 | memcpy (mem + c_size, "\n", 1); |
340 | break; | 359 | c_size ++; |
341 | if (0 > FPRINTF (fp, "%s\n", "")) | ||
342 | { | ||
343 | error = 1; | ||
344 | break; | ||
345 | } | ||
346 | sec = sec->next; | 360 | sec = sec->next; |
347 | } | 361 | } |
348 | if (error != 0) | 362 | GNUNET_assert (c_size == m_size); |
349 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", filename); | 363 | *size = c_size; |
350 | GNUNET_assert (0 == FCLOSE (fp)); | 364 | return mem; |
351 | if (error != 0) | 365 | } |
366 | |||
367 | |||
368 | /** | ||
369 | * Write configuration file. | ||
370 | * | ||
371 | * @param cfg configuration to write | ||
372 | * @param filename where to write the configuration | ||
373 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
374 | */ | ||
375 | int | ||
376 | GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, | ||
377 | const char *filename) | ||
378 | { | ||
379 | char *fn; | ||
380 | char *cfg_buf; | ||
381 | uint16_t size; | ||
382 | |||
383 | fn = GNUNET_STRINGS_filename_expand (filename); | ||
384 | if (fn == NULL) | ||
385 | return GNUNET_SYSERR; | ||
386 | if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) | ||
387 | { | ||
388 | GNUNET_free (fn); | ||
389 | return GNUNET_SYSERR; | ||
390 | } | ||
391 | cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size); | ||
392 | if (size != GNUNET_DISK_fn_write (fn, cfg_buf, size, | ||
393 | GNUNET_DISK_PERM_USER_READ | ||
394 | | GNUNET_DISK_PERM_USER_WRITE | ||
395 | | GNUNET_DISK_PERM_GROUP_READ | ||
396 | | GNUNET_DISK_PERM_GROUP_WRITE)) | ||
352 | { | 397 | { |
398 | GNUNET_free (fn); | ||
399 | GNUNET_free (cfg_buf); | ||
400 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
401 | "Writing configration to file: %s failed\n", filename); | ||
353 | cfg->dirty = GNUNET_SYSERR; /* last write failed */ | 402 | cfg->dirty = GNUNET_SYSERR; /* last write failed */ |
354 | return GNUNET_SYSERR; | 403 | return GNUNET_SYSERR; |
355 | } | 404 | } |
405 | GNUNET_free (fn); | ||
406 | GNUNET_free (cfg_buf); | ||
356 | cfg->dirty = GNUNET_NO; /* last write succeeded */ | 407 | cfg->dirty = GNUNET_NO; /* last write succeeded */ |
357 | return GNUNET_OK; | 408 | return GNUNET_OK; |
358 | } | 409 | } |