summaryrefslogtreecommitdiffstats
path: root/src/out-plutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/out-plutil.c')
-rw-r--r--src/out-plutil.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/out-plutil.c b/src/out-plutil.c
index d85f22c..5354aa3 100644
--- a/src/out-plutil.c
+++ b/src/out-plutil.c
@@ -38,6 +38,7 @@
38#include "plist.h" 38#include "plist.h"
39#include "strbuf.h" 39#include "strbuf.h"
40#include "time64.h" 40#include "time64.h"
41#include "hashtable.h"
41 42
42#define MAC_EPOCH 978307200 43#define MAC_EPOCH 978307200
43 44
@@ -304,19 +305,30 @@ static int num_digits_u(uint64_t i)
304 return n; 305 return n;
305} 306}
306 307
307static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth) 308static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, hashtable_t *visited)
308{ 309{
309 plist_data_t data; 310 plist_data_t data;
310 if (!node) { 311 if (!node) {
311 return PLIST_ERR_INVALID_ARG; 312 return PLIST_ERR_INVALID_ARG;
312 } 313 }
314
315 if (hash_table_lookup(visited, node)) {
316#if DEBUG
317 fprintf(stderr, "libplist: ERROR: circular reference detected\n");
318#endif
319 return PLIST_ERR_CIRCULAR_REF;
320 }
321
322 // mark as visited
323 hash_table_insert(visited, node, (void*)1);
324
313 data = plist_get_data(node); 325 data = plist_get_data(node);
314 if (node->children) { 326 if (node->children) {
315 node_t ch; 327 node_t ch;
316 unsigned int n_children = node_n_children(node); 328 unsigned int n_children = node_n_children(node);
317 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { 329 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
318 plist_err_t res = node_estimate_size(ch, size, depth + 1); 330 plist_err_t res = _node_estimate_size(ch, size, depth + 1, visited);
319 if (res < 0) { 331 if (res != PLIST_ERR_SUCCESS) {
320 return res; 332 return res;
321 } 333 }
322 } 334 }
@@ -388,6 +400,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept
388 return PLIST_ERR_SUCCESS; 400 return PLIST_ERR_SUCCESS;
389} 401}
390 402
403static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth)
404{
405 hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL);
406 if (!visited) return PLIST_ERR_NO_MEM;
407 plist_err_t err = _node_estimate_size(node, size, depth, visited);
408 hash_table_destroy(visited);
409 return err;
410}
411
391static plist_err_t _plist_write_to_strbuf(plist_t plist, strbuf_t *outbuf, plist_write_options_t options) 412static plist_err_t _plist_write_to_strbuf(plist_t plist, strbuf_t *outbuf, plist_write_options_t options)
392{ 413{
393 plist_err_t res = node_to_string((node_t)plist, &outbuf, 0); 414 plist_err_t res = node_to_string((node_t)plist, &outbuf, 0);