root/lib/talloc/talloc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. talloc_set_abort_fn
  2. talloc_abort
  3. talloc_abort_double_free
  4. talloc_abort_unknown_value
  5. talloc_chunk_from_ptr
  6. talloc_parent_chunk
  7. talloc_parent
  8. talloc_parent_name
  9. talloc_pool_objectcount
  10. talloc_alloc_pool
  11. __talloc
  12. talloc_pool
  13. _talloc_set_destructor
  14. talloc_increase_ref_count
  15. talloc_reference_destructor
  16. _talloc_set_name_const
  17. _talloc_named_const
  18. _talloc_reference
  19. _talloc_free
  20. _talloc_steal
  21. talloc_unreference
  22. talloc_unlink
  23. talloc_set_name_v
  24. talloc_set_name
  25. talloc_named
  26. talloc_get_name
  27. talloc_check_name
  28. talloc_abort_type_missmatch
  29. _talloc_get_type_abort
  30. talloc_init
  31. talloc_free_children
  32. _talloc
  33. talloc_set_name_const
  34. talloc_named_const
  35. talloc_free
  36. _talloc_realloc
  37. _talloc_move
  38. talloc_total_size
  39. talloc_total_blocks
  40. talloc_reference_count
  41. talloc_report_depth_cb
  42. talloc_report_depth_FILE_helper
  43. talloc_report_depth_file
  44. talloc_report_full
  45. talloc_report
  46. talloc_report_null
  47. talloc_report_null_full
  48. talloc_enable_null_tracking
  49. talloc_disable_null_tracking
  50. talloc_enable_leak_report
  51. talloc_enable_leak_report_full
  52. _talloc_zero
  53. _talloc_memdup
  54. __talloc_strlendup
  55. talloc_strdup
  56. talloc_strndup
  57. __talloc_strlendup_append
  58. talloc_strdup_append
  59. talloc_strdup_append_buffer
  60. talloc_strndup_append
  61. talloc_strndup_append_buffer
  62. talloc_vasprintf
  63. talloc_asprintf
  64. __talloc_vaslenprintf_append
  65. talloc_vasprintf_append
  66. talloc_vasprintf_append_buffer
  67. talloc_asprintf_append
  68. talloc_asprintf_append_buffer
  69. _talloc_array
  70. _talloc_zero_array
  71. _talloc_realloc_array
  72. talloc_realloc_fn
  73. talloc_autofree_destructor
  74. talloc_autofree
  75. talloc_autofree_context
  76. talloc_get_size
  77. talloc_find_parent_byname
  78. talloc_show_parents
  79. talloc_is_parent

   1 /* 
   2    Samba Unix SMB/CIFS implementation.
   3 
   4    Samba trivial allocation library - new interface
   5 
   6    NOTE: Please read talloc_guide.txt for full documentation
   7 
   8    Copyright (C) Andrew Tridgell 2004
   9    Copyright (C) Stefan Metzmacher 2006
  10    
  11      ** NOTE! The following LGPL license applies to the talloc
  12      ** library. This does NOT imply that all of Samba is released
  13      ** under the LGPL
  14    
  15    This library is free software; you can redistribute it and/or
  16    modify it under the terms of the GNU Lesser General Public
  17    License as published by the Free Software Foundation; either
  18    version 3 of the License, or (at your option) any later version.
  19 
  20    This library is distributed in the hope that it will be useful,
  21    but WITHOUT ANY WARRANTY; without even the implied warranty of
  22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  23    Lesser General Public License for more details.
  24 
  25    You should have received a copy of the GNU Lesser General Public
  26    License along with this library; if not, see <http://www.gnu.org/licenses/>.
  27 */
  28 
  29 /*
  30   inspired by http://swapped.cc/halloc/
  31 */
  32 
  33 #ifdef _SAMBA_BUILD_
  34 #include "version.h"
  35 #if (SAMBA_VERSION_MAJOR<4)
  36 #include "includes.h"
  37 /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
  38  * we trust ourselves... */
  39 #ifdef malloc
  40 #undef malloc
  41 #endif
  42 #ifdef realloc
  43 #undef realloc
  44 #endif
  45 #define _TALLOC_SAMBA3
  46 #endif /* (SAMBA_VERSION_MAJOR<4) */
  47 #endif /* _SAMBA_BUILD_ */
  48 
  49 #ifndef _TALLOC_SAMBA3
  50 #include "replace.h"
  51 #include "talloc.h"
  52 #endif /* not _TALLOC_SAMBA3 */
  53 
  54 /* use this to force every realloc to change the pointer, to stress test
  55    code that might not cope */
  56 #define ALWAYS_REALLOC 0
  57 
  58 
  59 #define MAX_TALLOC_SIZE 0x10000000
  60 #define TALLOC_MAGIC 0xe814ec70
  61 #define TALLOC_FLAG_FREE 0x01
  62 #define TALLOC_FLAG_LOOP 0x02
  63 #define TALLOC_FLAG_POOL 0x04           /* This is a talloc pool */
  64 #define TALLOC_FLAG_POOLMEM 0x08        /* This is allocated in a pool */
  65 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
  66 
  67 /* by default we abort when given a bad pointer (such as when talloc_free() is called 
  68    on a pointer that came from malloc() */
  69 #ifndef TALLOC_ABORT
  70 #define TALLOC_ABORT(reason) abort()
  71 #endif
  72 
  73 #ifndef discard_const_p
  74 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
  75 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
  76 #else
  77 # define discard_const_p(type, ptr) ((type *)(ptr))
  78 #endif
  79 #endif
  80 
  81 /* these macros gain us a few percent of speed on gcc */
  82 #if (__GNUC__ >= 3)
  83 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
  84    as its first argument */
  85 #ifndef likely
  86 #define likely(x)   __builtin_expect(!!(x), 1)
  87 #endif
  88 #ifndef unlikely
  89 #define unlikely(x) __builtin_expect(!!(x), 0)
  90 #endif
  91 #else
  92 #ifndef likely
  93 #define likely(x) (x)
  94 #endif
  95 #ifndef unlikely
  96 #define unlikely(x) (x)
  97 #endif
  98 #endif
  99 
 100 /* this null_context is only used if talloc_enable_leak_report() or
 101    talloc_enable_leak_report_full() is called, otherwise it remains
 102    NULL
 103 */
 104 static void *null_context;
 105 static void *autofree_context;
 106 
 107 struct talloc_reference_handle {
 108         struct talloc_reference_handle *next, *prev;
 109         void *ptr;
 110 };
 111 
 112 typedef int (*talloc_destructor_t)(void *);
 113 
 114 struct talloc_chunk {
 115         struct talloc_chunk *next, *prev;
 116         struct talloc_chunk *parent, *child;
 117         struct talloc_reference_handle *refs;
 118         talloc_destructor_t destructor;
 119         const char *name;
 120         size_t size;
 121         unsigned flags;
 122 
 123         /*
 124          * "pool" has dual use:
 125          *
 126          * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
 127          * marks the end of the currently allocated area.
 128          *
 129          * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
 130          * is a pointer to the struct talloc_chunk of the pool that it was
 131          * allocated from. This way children can quickly find the pool to chew
 132          * from.
 133          */
 134         void *pool;
 135 };
 136 
 137 /* 16 byte alignment seems to keep everyone happy */
 138 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
 139 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
 140 
 141 static void (*talloc_abort_fn)(const char *reason);
 142 
 143 void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
     /* [<][>][^][v][top][bottom][index][help] */
 144 {
 145         talloc_abort_fn = abort_fn;
 146 }
 147 
 148 static void talloc_abort(const char *reason)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150         if (!talloc_abort_fn) {
 151                 TALLOC_ABORT(reason);
 152         }
 153 
 154         talloc_abort_fn(reason);
 155 }
 156 
 157 static void talloc_abort_double_free(void)
     /* [<][>][^][v][top][bottom][index][help] */
 158 {
 159         talloc_abort("Bad talloc magic value - double free");
 160 }
 161 
 162 static void talloc_abort_unknown_value(void)
     /* [<][>][^][v][top][bottom][index][help] */
 163 {
 164         talloc_abort("Bad talloc magic value - unknown value");
 165 }
 166 
 167 /* panic if we get a bad magic value */
 168 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 169 {
 170         const char *pp = (const char *)ptr;
 171         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
 172         if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { 
 173                 if (tc->flags & TALLOC_FLAG_FREE) {
 174                         talloc_abort_double_free();
 175                 } else {
 176                         talloc_abort_unknown_value();
 177                 }
 178         }
 179         return tc;
 180 }
 181 
 182 /* hook into the front of the list */
 183 #define _TLIST_ADD(list, p) \
 184 do { \
 185         if (!(list)) { \
 186                 (list) = (p); \
 187                 (p)->next = (p)->prev = NULL; \
 188         } else { \
 189                 (list)->prev = (p); \
 190                 (p)->next = (list); \
 191                 (p)->prev = NULL; \
 192                 (list) = (p); \
 193         }\
 194 } while (0)
 195 
 196 /* remove an element from a list - element doesn't have to be in list. */
 197 #define _TLIST_REMOVE(list, p) \
 198 do { \
 199         if ((p) == (list)) { \
 200                 (list) = (p)->next; \
 201                 if (list) (list)->prev = NULL; \
 202         } else { \
 203                 if ((p)->prev) (p)->prev->next = (p)->next; \
 204                 if ((p)->next) (p)->next->prev = (p)->prev; \
 205         } \
 206         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
 207 } while (0)
 208 
 209 
 210 /*
 211   return the parent chunk of a pointer
 212 */
 213 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 214 {
 215         struct talloc_chunk *tc;
 216 
 217         if (unlikely(ptr == NULL)) {
 218                 return NULL;
 219         }
 220 
 221         tc = talloc_chunk_from_ptr(ptr);
 222         while (tc->prev) tc=tc->prev;
 223 
 224         return tc->parent;
 225 }
 226 
 227 void *talloc_parent(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 228 {
 229         struct talloc_chunk *tc = talloc_parent_chunk(ptr);
 230         return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
 231 }
 232 
 233 /*
 234   find parents name
 235 */
 236 const char *talloc_parent_name(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 237 {
 238         struct talloc_chunk *tc = talloc_parent_chunk(ptr);
 239         return tc? tc->name : NULL;
 240 }
 241 
 242 /*
 243   A pool carries an in-pool object count count in the first 16 bytes.
 244   bytes. This is done to support talloc_steal() to a parent outside of the
 245   pool. The count includes the pool itself, so a talloc_free() on a pool will
 246   only destroy the pool if the count has dropped to zero. A talloc_free() of a
 247   pool member will reduce the count, and eventually also call free(3) on the
 248   pool memory.
 249 
 250   The object count is not put into "struct talloc_chunk" because it is only
 251   relevant for talloc pools and the alignment to 16 bytes would increase the
 252   memory footprint of each talloc chunk by those 16 bytes.
 253 */
 254 
 255 #define TALLOC_POOL_HDR_SIZE 16
 256 
 257 static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
     /* [<][>][^][v][top][bottom][index][help] */
 258 {
 259         return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
 260 }
 261 
 262 /*
 263   Allocate from a pool
 264 */
 265 
 266 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
     /* [<][>][^][v][top][bottom][index][help] */
 267                                               size_t size)
 268 {
 269         struct talloc_chunk *pool_ctx = NULL;
 270         size_t space_left;
 271         struct talloc_chunk *result;
 272         size_t chunk_size;
 273 
 274         if (parent == NULL) {
 275                 return NULL;
 276         }
 277 
 278         if (parent->flags & TALLOC_FLAG_POOL) {
 279                 pool_ctx = parent;
 280         }
 281         else if (parent->flags & TALLOC_FLAG_POOLMEM) {
 282                 pool_ctx = (struct talloc_chunk *)parent->pool;
 283         }
 284 
 285         if (pool_ctx == NULL) {
 286                 return NULL;
 287         }
 288 
 289         space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
 290                 - ((char *)pool_ctx->pool);
 291 
 292         /*
 293          * Align size to 16 bytes
 294          */
 295         chunk_size = ((size + 15) & ~15);
 296 
 297         if (space_left < chunk_size) {
 298                 return NULL;
 299         }
 300 
 301         result = (struct talloc_chunk *)pool_ctx->pool;
 302 
 303 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
 304         VALGRIND_MAKE_MEM_UNDEFINED(result, size);
 305 #endif
 306 
 307         pool_ctx->pool = (void *)((char *)result + chunk_size);
 308 
 309         result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
 310         result->pool = pool_ctx;
 311 
 312         *talloc_pool_objectcount(pool_ctx) += 1;
 313 
 314         return result;
 315 }
 316 
 317 /* 
 318    Allocate a bit of memory as a child of an existing pointer
 319 */
 320 static inline void *__talloc(const void *context, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 321 {
 322         struct talloc_chunk *tc = NULL;
 323 
 324         if (unlikely(context == NULL)) {
 325                 context = null_context;
 326         }
 327 
 328         if (unlikely(size >= MAX_TALLOC_SIZE)) {
 329                 return NULL;
 330         }
 331 
 332         if (context != NULL) {
 333                 tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
 334                                        TC_HDR_SIZE+size);
 335         }
 336 
 337         if (tc == NULL) {
 338                 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
 339                 if (unlikely(tc == NULL)) return NULL;
 340                 tc->flags = TALLOC_MAGIC;
 341                 tc->pool  = NULL;
 342         }
 343 
 344         tc->size = size;
 345         tc->destructor = NULL;
 346         tc->child = NULL;
 347         tc->name = NULL;
 348         tc->refs = NULL;
 349 
 350         if (likely(context)) {
 351                 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
 352 
 353                 if (parent->child) {
 354                         parent->child->parent = NULL;
 355                         tc->next = parent->child;
 356                         tc->next->prev = tc;
 357                 } else {
 358                         tc->next = NULL;
 359                 }
 360                 tc->parent = parent;
 361                 tc->prev = NULL;
 362                 parent->child = tc;
 363         } else {
 364                 tc->next = tc->prev = tc->parent = NULL;
 365         }
 366 
 367         return TC_PTR_FROM_CHUNK(tc);
 368 }
 369 
 370 /*
 371  * Create a talloc pool
 372  */
 373 
 374 void *talloc_pool(const void *context, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 375 {
 376         void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
 377         struct talloc_chunk *tc;
 378 
 379         if (unlikely(result == NULL)) {
 380                 return NULL;
 381         }
 382 
 383         tc = talloc_chunk_from_ptr(result);
 384 
 385         tc->flags |= TALLOC_FLAG_POOL;
 386         tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
 387 
 388         *talloc_pool_objectcount(tc) = 1;
 389 
 390 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
 391         VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
 392 #endif
 393 
 394         return result;
 395 }
 396 
 397 /*
 398   setup a destructor to be called on free of a pointer
 399   the destructor should return 0 on success, or -1 on failure.
 400   if the destructor fails then the free is failed, and the memory can
 401   be continued to be used
 402 */
 403 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
     /* [<][>][^][v][top][bottom][index][help] */
 404 {
 405         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
 406         tc->destructor = destructor;
 407 }
 408 
 409 /*
 410   increase the reference count on a piece of memory. 
 411 */
 412 int talloc_increase_ref_count(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 413 {
 414         if (unlikely(!talloc_reference(null_context, ptr))) {
 415                 return -1;
 416         }
 417         return 0;
 418 }
 419 
 420 /*
 421   helper for talloc_reference()
 422 
 423   this is referenced by a function pointer and should not be inline
 424 */
 425 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
     /* [<][>][^][v][top][bottom][index][help] */
 426 {
 427         struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
 428         _TLIST_REMOVE(ptr_tc->refs, handle);
 429         return 0;
 430 }
 431 
 432 /*
 433    more efficient way to add a name to a pointer - the name must point to a 
 434    true string constant
 435 */
 436 static inline void _talloc_set_name_const(const void *ptr, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 437 {
 438         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
 439         tc->name = name;
 440 }
 441 
 442 /*
 443   internal talloc_named_const()
 444 */
 445 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 446 {
 447         void *ptr;
 448 
 449         ptr = __talloc(context, size);
 450         if (unlikely(ptr == NULL)) {
 451                 return NULL;
 452         }
 453 
 454         _talloc_set_name_const(ptr, name);
 455 
 456         return ptr;
 457 }
 458 
 459 /*
 460   make a secondary reference to a pointer, hanging off the given context.
 461   the pointer remains valid until both the original caller and this given
 462   context are freed.
 463   
 464   the major use for this is when two different structures need to reference the 
 465   same underlying data, and you want to be able to free the two instances separately,
 466   and in either order
 467 */
 468 void *_talloc_reference(const void *context, const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 469 {
 470         struct talloc_chunk *tc;
 471         struct talloc_reference_handle *handle;
 472         if (unlikely(ptr == NULL)) return NULL;
 473 
 474         tc = talloc_chunk_from_ptr(ptr);
 475         handle = (struct talloc_reference_handle *)_talloc_named_const(context,
 476                                                    sizeof(struct talloc_reference_handle),
 477                                                    TALLOC_MAGIC_REFERENCE);
 478         if (unlikely(handle == NULL)) return NULL;
 479 
 480         /* note that we hang the destructor off the handle, not the
 481            main context as that allows the caller to still setup their
 482            own destructor on the context if they want to */
 483         talloc_set_destructor(handle, talloc_reference_destructor);
 484         handle->ptr = discard_const_p(void, ptr);
 485         _TLIST_ADD(tc->refs, handle);
 486         return handle->ptr;
 487 }
 488 
 489 
 490 /* 
 491    internal talloc_free call
 492 */
 493 static inline int _talloc_free(void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 494 {
 495         struct talloc_chunk *tc;
 496 
 497         if (unlikely(ptr == NULL)) {
 498                 return -1;
 499         }
 500 
 501         tc = talloc_chunk_from_ptr(ptr);
 502 
 503         if (unlikely(tc->refs)) {
 504                 int is_child;
 505                 /* check this is a reference from a child or grantchild
 506                  * back to it's parent or grantparent
 507                  *
 508                  * in that case we need to remove the reference and
 509                  * call another instance of talloc_free() on the current
 510                  * pointer.
 511                  */
 512                 is_child = talloc_is_parent(tc->refs, ptr);
 513                 _talloc_free(tc->refs);
 514                 if (is_child) {
 515                         return _talloc_free(ptr);
 516                 }
 517                 return -1;
 518         }
 519 
 520         if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
 521                 /* we have a free loop - stop looping */
 522                 return 0;
 523         }
 524 
 525         if (unlikely(tc->destructor)) {
 526                 talloc_destructor_t d = tc->destructor;
 527                 if (d == (talloc_destructor_t)-1) {
 528                         return -1;
 529                 }
 530                 tc->destructor = (talloc_destructor_t)-1;
 531                 if (d(ptr) == -1) {
 532                         tc->destructor = d;
 533                         return -1;
 534                 }
 535                 tc->destructor = NULL;
 536         }
 537 
 538         if (tc->parent) {
 539                 _TLIST_REMOVE(tc->parent->child, tc);
 540                 if (tc->parent->child) {
 541                         tc->parent->child->parent = tc->parent;
 542                 }
 543         } else {
 544                 if (tc->prev) tc->prev->next = tc->next;
 545                 if (tc->next) tc->next->prev = tc->prev;
 546         }
 547 
 548         tc->flags |= TALLOC_FLAG_LOOP;
 549 
 550         while (tc->child) {
 551                 /* we need to work out who will own an abandoned child
 552                    if it cannot be freed. In priority order, the first
 553                    choice is owner of any remaining reference to this
 554                    pointer, the second choice is our parent, and the
 555                    final choice is the null context. */
 556                 void *child = TC_PTR_FROM_CHUNK(tc->child);
 557                 const void *new_parent = null_context;
 558                 if (unlikely(tc->child->refs)) {
 559                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
 560                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 561                 }
 562                 if (unlikely(_talloc_free(child) == -1)) {
 563                         if (new_parent == null_context) {
 564                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
 565                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 566                         }
 567                         talloc_steal(new_parent, child);
 568                 }
 569         }
 570 
 571         tc->flags |= TALLOC_FLAG_FREE;
 572 
 573         if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
 574                 struct talloc_chunk *pool;
 575                 unsigned int *pool_object_count;
 576 
 577                 pool = (tc->flags & TALLOC_FLAG_POOL)
 578                         ? tc : (struct talloc_chunk *)tc->pool;
 579 
 580                 pool_object_count = talloc_pool_objectcount(pool);
 581 
 582                 if (*pool_object_count == 0) {
 583                         talloc_abort("Pool object count zero!");
 584                 }
 585 
 586                 *pool_object_count -= 1;
 587 
 588                 if (*pool_object_count == 0) {
 589                         free(pool);
 590                 }
 591         }
 592         else {
 593                 free(tc);
 594         }
 595         return 0;
 596 }
 597 
 598 /* 
 599    move a lump of memory from one talloc context to another return the
 600    ptr on success, or NULL if it could not be transferred.
 601    passing NULL as ptr will always return NULL with no side effects.
 602 */
 603 void *_talloc_steal(const void *new_ctx, const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 604 {
 605         struct talloc_chunk *tc, *new_tc;
 606 
 607         if (unlikely(!ptr)) {
 608                 return NULL;
 609         }
 610 
 611         if (unlikely(new_ctx == NULL)) {
 612                 new_ctx = null_context;
 613         }
 614 
 615         tc = talloc_chunk_from_ptr(ptr);
 616 
 617         if (unlikely(new_ctx == NULL)) {
 618                 if (tc->parent) {
 619                         _TLIST_REMOVE(tc->parent->child, tc);
 620                         if (tc->parent->child) {
 621                                 tc->parent->child->parent = tc->parent;
 622                         }
 623                 } else {
 624                         if (tc->prev) tc->prev->next = tc->next;
 625                         if (tc->next) tc->next->prev = tc->prev;
 626                 }
 627                 
 628                 tc->parent = tc->next = tc->prev = NULL;
 629                 return discard_const_p(void, ptr);
 630         }
 631 
 632         new_tc = talloc_chunk_from_ptr(new_ctx);
 633 
 634         if (unlikely(tc == new_tc || tc->parent == new_tc)) {
 635                 return discard_const_p(void, ptr);
 636         }
 637 
 638         if (tc->parent) {
 639                 _TLIST_REMOVE(tc->parent->child, tc);
 640                 if (tc->parent->child) {
 641                         tc->parent->child->parent = tc->parent;
 642                 }
 643         } else {
 644                 if (tc->prev) tc->prev->next = tc->next;
 645                 if (tc->next) tc->next->prev = tc->prev;
 646         }
 647 
 648         tc->parent = new_tc;
 649         if (new_tc->child) new_tc->child->parent = NULL;
 650         _TLIST_ADD(new_tc->child, tc);
 651 
 652         return discard_const_p(void, ptr);
 653 }
 654 
 655 
 656 
 657 /*
 658   remove a secondary reference to a pointer. This undo's what
 659   talloc_reference() has done. The context and pointer arguments
 660   must match those given to a talloc_reference()
 661 */
 662 static inline int talloc_unreference(const void *context, const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 663 {
 664         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
 665         struct talloc_reference_handle *h;
 666 
 667         if (unlikely(context == NULL)) {
 668                 context = null_context;
 669         }
 670 
 671         for (h=tc->refs;h;h=h->next) {
 672                 struct talloc_chunk *p = talloc_parent_chunk(h);
 673                 if (p == NULL) {
 674                         if (context == NULL) break;
 675                 } else if (TC_PTR_FROM_CHUNK(p) == context) {
 676                         break;
 677                 }
 678         }
 679         if (h == NULL) {
 680                 return -1;
 681         }
 682 
 683         return _talloc_free(h);
 684 }
 685 
 686 /*
 687   remove a specific parent context from a pointer. This is a more
 688   controlled varient of talloc_free()
 689 */
 690 int talloc_unlink(const void *context, void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 691 {
 692         struct talloc_chunk *tc_p, *new_p;
 693         void *new_parent;
 694 
 695         if (ptr == NULL) {
 696                 return -1;
 697         }
 698 
 699         if (context == NULL) {
 700                 context = null_context;
 701         }
 702 
 703         if (talloc_unreference(context, ptr) == 0) {
 704                 return 0;
 705         }
 706 
 707         if (context == NULL) {
 708                 if (talloc_parent_chunk(ptr) != NULL) {
 709                         return -1;
 710                 }
 711         } else {
 712                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
 713                         return -1;
 714                 }
 715         }
 716         
 717         tc_p = talloc_chunk_from_ptr(ptr);
 718 
 719         if (tc_p->refs == NULL) {
 720                 return _talloc_free(ptr);
 721         }
 722 
 723         new_p = talloc_parent_chunk(tc_p->refs);
 724         if (new_p) {
 725                 new_parent = TC_PTR_FROM_CHUNK(new_p);
 726         } else {
 727                 new_parent = NULL;
 728         }
 729 
 730         if (talloc_unreference(new_parent, ptr) != 0) {
 731                 return -1;
 732         }
 733 
 734         talloc_steal(new_parent, ptr);
 735 
 736         return 0;
 737 }
 738 
 739 /*
 740   add a name to an existing pointer - va_list version
 741 */
 742 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
     /* [<][>][^][v][top][bottom][index][help] */
 743 
 744 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
 745 {
 746         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
 747         tc->name = talloc_vasprintf(ptr, fmt, ap);
 748         if (likely(tc->name)) {
 749                 _talloc_set_name_const(tc->name, ".name");
 750         }
 751         return tc->name;
 752 }
 753 
 754 /*
 755   add a name to an existing pointer
 756 */
 757 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 758 {
 759         const char *name;
 760         va_list ap;
 761         va_start(ap, fmt);
 762         name = talloc_set_name_v(ptr, fmt, ap);
 763         va_end(ap);
 764         return name;
 765 }
 766 
 767 
 768 /*
 769   create a named talloc pointer. Any talloc pointer can be named, and
 770   talloc_named() operates just like talloc() except that it allows you
 771   to name the pointer.
 772 */
 773 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 774 {
 775         va_list ap;
 776         void *ptr;
 777         const char *name;
 778 
 779         ptr = __talloc(context, size);
 780         if (unlikely(ptr == NULL)) return NULL;
 781 
 782         va_start(ap, fmt);
 783         name = talloc_set_name_v(ptr, fmt, ap);
 784         va_end(ap);
 785 
 786         if (unlikely(name == NULL)) {
 787                 _talloc_free(ptr);
 788                 return NULL;
 789         }
 790 
 791         return ptr;
 792 }
 793 
 794 /*
 795   return the name of a talloc ptr, or "UNNAMED"
 796 */
 797 const char *talloc_get_name(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 798 {
 799         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
 800         if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
 801                 return ".reference";
 802         }
 803         if (likely(tc->name)) {
 804                 return tc->name;
 805         }
 806         return "UNNAMED";
 807 }
 808 
 809 
 810 /*
 811   check if a pointer has the given name. If it does, return the pointer,
 812   otherwise return NULL
 813 */
 814 void *talloc_check_name(const void *ptr, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 815 {
 816         const char *pname;
 817         if (unlikely(ptr == NULL)) return NULL;
 818         pname = talloc_get_name(ptr);
 819         if (likely(pname == name || strcmp(pname, name) == 0)) {
 820                 return discard_const_p(void, ptr);
 821         }
 822         return NULL;
 823 }
 824 
 825 static void talloc_abort_type_missmatch(const char *location,
     /* [<][>][^][v][top][bottom][index][help] */
 826                                         const char *name,
 827                                         const char *expected)
 828 {
 829         const char *reason;
 830 
 831         reason = talloc_asprintf(NULL,
 832                                  "%s: Type mismatch: name[%s] expected[%s]",
 833                                  location,
 834                                  name?name:"NULL",
 835                                  expected);
 836         if (!reason) {
 837                 reason = "Type mismatch";
 838         }
 839 
 840         talloc_abort(reason);
 841 }
 842 
 843 void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
     /* [<][>][^][v][top][bottom][index][help] */
 844 {
 845         const char *pname;
 846 
 847         if (unlikely(ptr == NULL)) {
 848                 talloc_abort_type_missmatch(location, NULL, name);
 849                 return NULL;
 850         }
 851 
 852         pname = talloc_get_name(ptr);
 853         if (likely(pname == name || strcmp(pname, name) == 0)) {
 854                 return discard_const_p(void, ptr);
 855         }
 856 
 857         talloc_abort_type_missmatch(location, pname, name);
 858         return NULL;
 859 }
 860 
 861 /*
 862   this is for compatibility with older versions of talloc
 863 */
 864 void *talloc_init(const char *fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 865 {
 866         va_list ap;
 867         void *ptr;
 868         const char *name;
 869 
 870         /*
 871          * samba3 expects talloc_report_depth_cb(NULL, ...)
 872          * reports all talloc'ed memory, so we need to enable
 873          * null_tracking
 874          */
 875         talloc_enable_null_tracking();
 876 
 877         ptr = __talloc(NULL, 0);
 878         if (unlikely(ptr == NULL)) return NULL;
 879 
 880         va_start(ap, fmt);
 881         name = talloc_set_name_v(ptr, fmt, ap);
 882         va_end(ap);
 883 
 884         if (unlikely(name == NULL)) {
 885                 _talloc_free(ptr);
 886                 return NULL;
 887         }
 888 
 889         return ptr;
 890 }
 891 
 892 /*
 893   this is a replacement for the Samba3 talloc_destroy_pool functionality. It
 894   should probably not be used in new code. It's in here to keep the talloc
 895   code consistent across Samba 3 and 4.
 896 */
 897 void talloc_free_children(void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 898 {
 899         struct talloc_chunk *tc;
 900 
 901         if (unlikely(ptr == NULL)) {
 902                 return;
 903         }
 904 
 905         tc = talloc_chunk_from_ptr(ptr);
 906 
 907         while (tc->child) {
 908                 /* we need to work out who will own an abandoned child
 909                    if it cannot be freed. In priority order, the first
 910                    choice is owner of any remaining reference to this
 911                    pointer, the second choice is our parent, and the
 912                    final choice is the null context. */
 913                 void *child = TC_PTR_FROM_CHUNK(tc->child);
 914                 const void *new_parent = null_context;
 915                 if (unlikely(tc->child->refs)) {
 916                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
 917                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 918                 }
 919                 if (unlikely(_talloc_free(child) == -1)) {
 920                         if (new_parent == null_context) {
 921                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
 922                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 923                         }
 924                         talloc_steal(new_parent, child);
 925                 }
 926         }
 927 
 928         if ((tc->flags & TALLOC_FLAG_POOL)
 929             && (*talloc_pool_objectcount(tc) == 1)) {
 930                 tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
 931 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
 932                 VALGRIND_MAKE_MEM_NOACCESS(
 933                         tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
 934 #endif
 935         }
 936 }
 937 
 938 /* 
 939    Allocate a bit of memory as a child of an existing pointer
 940 */
 941 void *_talloc(const void *context, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 942 {
 943         return __talloc(context, size);
 944 }
 945 
 946 /*
 947   externally callable talloc_set_name_const()
 948 */
 949 void talloc_set_name_const(const void *ptr, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 950 {
 951         _talloc_set_name_const(ptr, name);
 952 }
 953 
 954 /*
 955   create a named talloc pointer. Any talloc pointer can be named, and
 956   talloc_named() operates just like talloc() except that it allows you
 957   to name the pointer.
 958 */
 959 void *talloc_named_const(const void *context, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 960 {
 961         return _talloc_named_const(context, size, name);
 962 }
 963 
 964 /* 
 965    free a talloc pointer. This also frees all child pointers of this 
 966    pointer recursively
 967 
 968    return 0 if the memory is actually freed, otherwise -1. The memory
 969    will not be freed if the ref_count is > 1 or the destructor (if
 970    any) returns non-zero
 971 */
 972 int talloc_free(void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 973 {
 974         return _talloc_free(ptr);
 975 }
 976 
 977 
 978 
 979 /*
 980   A talloc version of realloc. The context argument is only used if
 981   ptr is NULL
 982 */
 983 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 984 {
 985         struct talloc_chunk *tc;
 986         void *new_ptr;
 987         bool malloced = false;
 988 
 989         /* size zero is equivalent to free() */
 990         if (unlikely(size == 0)) {
 991                 _talloc_free(ptr);
 992                 return NULL;
 993         }
 994 
 995         if (unlikely(size >= MAX_TALLOC_SIZE)) {
 996                 return NULL;
 997         }
 998 
 999         /* realloc(NULL) is equivalent to malloc() */
1000         if (ptr == NULL) {
1001                 return _talloc_named_const(context, size, name);
1002         }
1003 
1004         tc = talloc_chunk_from_ptr(ptr);
1005 
1006         /* don't allow realloc on referenced pointers */
1007         if (unlikely(tc->refs)) {
1008                 return NULL;
1009         }
1010 
1011         /* don't shrink if we have less than 1k to gain */
1012         if ((size < tc->size) && ((tc->size - size) < 1024)) {
1013                 tc->size = size;
1014                 return ptr;
1015         }
1016 
1017         /* by resetting magic we catch users of the old memory */
1018         tc->flags |= TALLOC_FLAG_FREE;
1019 
1020 #if ALWAYS_REALLOC
1021         new_ptr = malloc(size + TC_HDR_SIZE);
1022         if (new_ptr) {
1023                 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
1024                 free(tc);
1025         }
1026 #else
1027         if (tc->flags & TALLOC_FLAG_POOLMEM) {
1028 
1029                 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1030                 *talloc_pool_objectcount((struct talloc_chunk *)
1031                                          (tc->pool)) -= 1;
1032 
1033                 if (new_ptr == NULL) {
1034                         new_ptr = malloc(TC_HDR_SIZE+size);
1035                         malloced = true;
1036                 }
1037 
1038                 if (new_ptr) {
1039                         memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1040                 }
1041         }
1042         else {
1043                 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1044         }
1045 #endif
1046         if (unlikely(!new_ptr)) {       
1047                 tc->flags &= ~TALLOC_FLAG_FREE; 
1048                 return NULL; 
1049         }
1050 
1051         tc = (struct talloc_chunk *)new_ptr;
1052         tc->flags &= ~TALLOC_FLAG_FREE;
1053         if (malloced) {
1054                 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1055         }
1056         if (tc->parent) {
1057                 tc->parent->child = tc;
1058         }
1059         if (tc->child) {
1060                 tc->child->parent = tc;
1061         }
1062 
1063         if (tc->prev) {
1064                 tc->prev->next = tc;
1065         }
1066         if (tc->next) {
1067                 tc->next->prev = tc;
1068         }
1069 
1070         tc->size = size;
1071         _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1072 
1073         return TC_PTR_FROM_CHUNK(tc);
1074 }
1075 
1076 /*
1077   a wrapper around talloc_steal() for situations where you are moving a pointer
1078   between two structures, and want the old pointer to be set to NULL
1079 */
1080 void *_talloc_move(const void *new_ctx, const void *_pptr)
     /* [<][>][^][v][top][bottom][index][help] */
1081 {
1082         const void **pptr = discard_const_p(const void *,_pptr);
1083         void *ret = _talloc_steal(new_ctx, *pptr);
1084         (*pptr) = NULL;
1085         return ret;
1086 }
1087 
1088 /*
1089   return the total size of a talloc pool (subtree)
1090 */
1091 size_t talloc_total_size(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
1092 {
1093         size_t total = 0;
1094         struct talloc_chunk *c, *tc;
1095 
1096         if (ptr == NULL) {
1097                 ptr = null_context;
1098         }
1099         if (ptr == NULL) {
1100                 return 0;
1101         }
1102 
1103         tc = talloc_chunk_from_ptr(ptr);
1104 
1105         if (tc->flags & TALLOC_FLAG_LOOP) {
1106                 return 0;
1107         }
1108 
1109         tc->flags |= TALLOC_FLAG_LOOP;
1110 
1111         total = tc->size;
1112         for (c=tc->child;c;c=c->next) {
1113                 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
1114         }
1115 
1116         tc->flags &= ~TALLOC_FLAG_LOOP;
1117 
1118         return total;
1119 }
1120 
1121 /*
1122   return the total number of blocks in a talloc pool (subtree)
1123 */
1124 size_t talloc_total_blocks(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
1125 {
1126         size_t total = 0;
1127         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
1128 
1129         if (tc->flags & TALLOC_FLAG_LOOP) {
1130                 return 0;
1131         }
1132 
1133         tc->flags |= TALLOC_FLAG_LOOP;
1134 
1135         total++;
1136         for (c=tc->child;c;c=c->next) {
1137                 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
1138         }
1139 
1140         tc->flags &= ~TALLOC_FLAG_LOOP;
1141 
1142         return total;
1143 }
1144 
1145 /*
1146   return the number of external references to a pointer
1147 */
1148 size_t talloc_reference_count(const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
1149 {
1150         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1151         struct talloc_reference_handle *h;
1152         size_t ret = 0;
1153 
1154         for (h=tc->refs;h;h=h->next) {
1155                 ret++;
1156         }
1157         return ret;
1158 }
1159 
1160 /*
1161   report on memory usage by all children of a pointer, giving a full tree view
1162 */
1163 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
     /* [<][>][^][v][top][bottom][index][help] */
1164                             void (*callback)(const void *ptr,
1165                                              int depth, int max_depth,
1166                                              int is_ref,
1167                                              void *private_data),
1168                             void *private_data)
1169 {
1170         struct talloc_chunk *c, *tc;
1171 
1172         if (ptr == NULL) {
1173                 ptr = null_context;
1174         }
1175         if (ptr == NULL) return;
1176 
1177         tc = talloc_chunk_from_ptr(ptr);
1178 
1179         if (tc->flags & TALLOC_FLAG_LOOP) {
1180                 return;
1181         }
1182 
1183         callback(ptr, depth, max_depth, 0, private_data);
1184 
1185         if (max_depth >= 0 && depth >= max_depth) {
1186                 return;
1187         }
1188 
1189         tc->flags |= TALLOC_FLAG_LOOP;
1190         for (c=tc->child;c;c=c->next) {
1191                 if (c->name == TALLOC_MAGIC_REFERENCE) {
1192                         struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1193                         callback(h->ptr, depth + 1, max_depth, 1, private_data);
1194                 } else {
1195                         talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1196                 }
1197         }
1198         tc->flags &= ~TALLOC_FLAG_LOOP;
1199 }
1200 
1201 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
     /* [<][>][^][v][top][bottom][index][help] */
1202 {
1203         const char *name = talloc_get_name(ptr);
1204         FILE *f = (FILE *)_f;
1205 
1206         if (is_ref) {
1207                 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1208                 return;
1209         }
1210 
1211         if (depth == 0) {
1212                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
1213                         (max_depth < 0 ? "full " :""), name,
1214                         (unsigned long)talloc_total_size(ptr),
1215                         (unsigned long)talloc_total_blocks(ptr));
1216                 return;
1217         }
1218 
1219         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
1220                 depth*4, "",
1221                 name,
1222                 (unsigned long)talloc_total_size(ptr),
1223                 (unsigned long)talloc_total_blocks(ptr),
1224                 (int)talloc_reference_count(ptr), ptr);
1225 
1226 #if 0
1227         fprintf(f, "content: ");
1228         if (talloc_total_size(ptr)) {
1229                 int tot = talloc_total_size(ptr);
1230                 int i;
1231 
1232                 for (i = 0; i < tot; i++) {
1233                         if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1234                                 fprintf(f, "%c", ((char *)ptr)[i]);
1235                         } else {
1236                                 fprintf(f, "~%02x", ((char *)ptr)[i]);
1237                         }
1238                 }
1239         }
1240         fprintf(f, "\n");
1241 #endif
1242 }
1243 
1244 /*
1245   report on memory usage by all children of a pointer, giving a full tree view
1246 */
1247 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
     /* [<][>][^][v][top][bottom][index][help] */
1248 {
1249         talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1250         fflush(f);
1251 }
1252 
1253 /*
1254   report on memory usage by all children of a pointer, giving a full tree view
1255 */
1256 void talloc_report_full(const void *ptr, FILE *f)
     /* [<][>][^][v][top][bottom][index][help] */
1257 {
1258         talloc_report_depth_file(ptr, 0, -1, f);
1259 }
1260 
1261 /*
1262   report on memory usage by all children of a pointer
1263 */
1264 void talloc_report(const void *ptr, FILE *f)
     /* [<][>][^][v][top][bottom][index][help] */
1265 {
1266         talloc_report_depth_file(ptr, 0, 1, f);
1267 }
1268 
1269 /*
1270   report on any memory hanging off the null context
1271 */
1272 static void talloc_report_null(void)
     /* [<][>][^][v][top][bottom][index][help] */
1273 {
1274         if (talloc_total_size(null_context) != 0) {
1275                 talloc_report(null_context, stderr);
1276         }
1277 }
1278 
1279 /*
1280   report on any memory hanging off the null context
1281 */
1282 static void talloc_report_null_full(void)
     /* [<][>][^][v][top][bottom][index][help] */
1283 {
1284         if (talloc_total_size(null_context) != 0) {
1285                 talloc_report_full(null_context, stderr);
1286         }
1287 }
1288 
1289 /*
1290   enable tracking of the NULL context
1291 */
1292 void talloc_enable_null_tracking(void)
     /* [<][>][^][v][top][bottom][index][help] */
1293 {
1294         if (null_context == NULL) {
1295                 null_context = _talloc_named_const(NULL, 0, "null_context");
1296         }
1297 }
1298 
1299 /*
1300   disable tracking of the NULL context
1301 */
1302 void talloc_disable_null_tracking(void)
     /* [<][>][^][v][top][bottom][index][help] */
1303 {
1304         _talloc_free(null_context);
1305         null_context = NULL;
1306 }
1307 
1308 /*
1309   enable leak reporting on exit
1310 */
1311 void talloc_enable_leak_report(void)
     /* [<][>][^][v][top][bottom][index][help] */
1312 {
1313         talloc_enable_null_tracking();
1314         atexit(talloc_report_null);
1315 }
1316 
1317 /*
1318   enable full leak reporting on exit
1319 */
1320 void talloc_enable_leak_report_full(void)
     /* [<][>][^][v][top][bottom][index][help] */
1321 {
1322         talloc_enable_null_tracking();
1323         atexit(talloc_report_null_full);
1324 }
1325 
1326 /* 
1327    talloc and zero memory. 
1328 */
1329 void *_talloc_zero(const void *ctx, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1330 {
1331         void *p = _talloc_named_const(ctx, size, name);
1332 
1333         if (p) {
1334                 memset(p, '\0', size);
1335         }
1336 
1337         return p;
1338 }
1339 
1340 /*
1341   memdup with a talloc. 
1342 */
1343 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1344 {
1345         void *newp = _talloc_named_const(t, size, name);
1346 
1347         if (likely(newp)) {
1348                 memcpy(newp, p, size);
1349         }
1350 
1351         return newp;
1352 }
1353 
1354 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
1355 {
1356         char *ret;
1357 
1358         ret = (char *)__talloc(t, len + 1);
1359         if (unlikely(!ret)) return NULL;
1360 
1361         memcpy(ret, p, len);
1362         ret[len] = 0;
1363 
1364         _talloc_set_name_const(ret, ret);
1365         return ret;
1366 }
1367 
1368 /*
1369   strdup with a talloc
1370 */
1371 char *talloc_strdup(const void *t, const char *p)
     /* [<][>][^][v][top][bottom][index][help] */
1372 {
1373         if (unlikely(!p)) return NULL;
1374         return __talloc_strlendup(t, p, strlen(p));
1375 }
1376 
1377 /*
1378   strndup with a talloc
1379 */
1380 char *talloc_strndup(const void *t, const char *p, size_t n)
     /* [<][>][^][v][top][bottom][index][help] */
1381 {
1382         if (unlikely(!p)) return NULL;
1383         return __talloc_strlendup(t, p, strnlen(p, n));
1384 }
1385 
1386 static inline char *__talloc_strlendup_append(char *s, size_t slen,
     /* [<][>][^][v][top][bottom][index][help] */
1387                                               const char *a, size_t alen)
1388 {
1389         char *ret;
1390 
1391         ret = talloc_realloc(NULL, s, char, slen + alen + 1);
1392         if (unlikely(!ret)) return NULL;
1393 
1394         /* append the string and the trailing \0 */
1395         memcpy(&ret[slen], a, alen);
1396         ret[slen+alen] = 0;
1397 
1398         _talloc_set_name_const(ret, ret);
1399         return ret;
1400 }
1401 
1402 /*
1403  * Appends at the end of the string.
1404  */
1405 char *talloc_strdup_append(char *s, const char *a)
     /* [<][>][^][v][top][bottom][index][help] */
1406 {
1407         if (unlikely(!s)) {
1408                 return talloc_strdup(NULL, a);
1409         }
1410 
1411         if (unlikely(!a)) {
1412                 return s;
1413         }
1414 
1415         return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
1416 }
1417 
1418 /*
1419  * Appends at the end of the talloc'ed buffer,
1420  * not the end of the string.
1421  */
1422 char *talloc_strdup_append_buffer(char *s, const char *a)
     /* [<][>][^][v][top][bottom][index][help] */
1423 {
1424         size_t slen;
1425 
1426         if (unlikely(!s)) {
1427                 return talloc_strdup(NULL, a);
1428         }
1429 
1430         if (unlikely(!a)) {
1431                 return s;
1432         }
1433 
1434         slen = talloc_get_size(s);
1435         if (likely(slen > 0)) {
1436                 slen--;
1437         }
1438 
1439         return __talloc_strlendup_append(s, slen, a, strlen(a));
1440 }
1441 
1442 /*
1443  * Appends at the end of the string.
1444  */
1445 char *talloc_strndup_append(char *s, const char *a, size_t n)
     /* [<][>][^][v][top][bottom][index][help] */
1446 {
1447         if (unlikely(!s)) {
1448                 return talloc_strdup(NULL, a);
1449         }
1450 
1451         if (unlikely(!a)) {
1452                 return s;
1453         }
1454 
1455         return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
1456 }
1457 
1458 /*
1459  * Appends at the end of the talloc'ed buffer,
1460  * not the end of the string.
1461  */
1462 char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
     /* [<][>][^][v][top][bottom][index][help] */
1463 {
1464         size_t slen;
1465 
1466         if (unlikely(!s)) {
1467                 return talloc_strdup(NULL, a);
1468         }
1469 
1470         if (unlikely(!a)) {
1471                 return s;
1472         }
1473 
1474         slen = talloc_get_size(s);
1475         if (likely(slen > 0)) {
1476                 slen--;
1477         }
1478 
1479         return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
1480 }
1481 
1482 #ifndef HAVE_VA_COPY
1483 #ifdef HAVE___VA_COPY
1484 #define va_copy(dest, src) __va_copy(dest, src)
1485 #else
1486 #define va_copy(dest, src) (dest) = (src)
1487 #endif
1488 #endif
1489 
1490 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
     /* [<][>][^][v][top][bottom][index][help] */
1491 {
1492         int len;
1493         char *ret;
1494         va_list ap2;
1495         char c;
1496 
1497         /* this call looks strange, but it makes it work on older solaris boxes */
1498         va_copy(ap2, ap);
1499         len = vsnprintf(&c, 1, fmt, ap2);
1500         va_end(ap2);
1501         if (unlikely(len < 0)) {
1502                 return NULL;
1503         }
1504 
1505         ret = (char *)__talloc(t, len+1);
1506         if (unlikely(!ret)) return NULL;
1507 
1508         va_copy(ap2, ap);
1509         vsnprintf(ret, len+1, fmt, ap2);
1510         va_end(ap2);
1511 
1512         _talloc_set_name_const(ret, ret);
1513         return ret;
1514 }
1515 
1516 
1517 /*
1518   Perform string formatting, and return a pointer to newly allocated
1519   memory holding the result, inside a memory pool.
1520  */
1521 char *talloc_asprintf(const void *t, const char *fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
1522 {
1523         va_list ap;
1524         char *ret;
1525 
1526         va_start(ap, fmt);
1527         ret = talloc_vasprintf(t, fmt, ap);
1528         va_end(ap);
1529         return ret;
1530 }
1531 
1532 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
     /* [<][>][^][v][top][bottom][index][help] */
1533                                                  const char *fmt, va_list ap)
1534                                                  PRINTF_ATTRIBUTE(3,0);
1535 
1536 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
1537                                                  const char *fmt, va_list ap)
1538 {
1539         ssize_t alen;
1540         va_list ap2;
1541         char c;
1542 
1543         va_copy(ap2, ap);
1544         alen = vsnprintf(&c, 1, fmt, ap2);
1545         va_end(ap2);
1546 
1547         if (alen <= 0) {
1548                 /* Either the vsnprintf failed or the format resulted in
1549                  * no characters being formatted. In the former case, we
1550                  * ought to return NULL, in the latter we ought to return
1551                  * the original string. Most current callers of this
1552                  * function expect it to never return NULL.
1553                  */
1554                 return s;
1555         }
1556 
1557         s = talloc_realloc(NULL, s, char, slen + alen + 1);
1558         if (!s) return NULL;
1559 
1560         va_copy(ap2, ap);
1561         vsnprintf(s + slen, alen + 1, fmt, ap2);
1562         va_end(ap2);
1563 
1564         _talloc_set_name_const(s, s);
1565         return s;
1566 }
1567 
1568 /**
1569  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1570  * and return @p s, which may have moved.  Good for gradually
1571  * accumulating output into a string buffer. Appends at the end
1572  * of the string.
1573  **/
1574 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
     /* [<][>][^][v][top][bottom][index][help] */
1575 {
1576         if (unlikely(!s)) {
1577                 return talloc_vasprintf(NULL, fmt, ap);
1578         }
1579 
1580         return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
1581 }
1582 
1583 /**
1584  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1585  * and return @p s, which may have moved. Always appends at the
1586  * end of the talloc'ed buffer, not the end of the string.
1587  **/
1588 char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
     /* [<][>][^][v][top][bottom][index][help] */
1589 {
1590         size_t slen;
1591 
1592         if (unlikely(!s)) {
1593                 return talloc_vasprintf(NULL, fmt, ap);
1594         }
1595 
1596         slen = talloc_get_size(s);
1597         if (likely(slen > 0)) {
1598                 slen--;
1599         }
1600 
1601         return __talloc_vaslenprintf_append(s, slen, fmt, ap);
1602 }
1603 
1604 /*
1605   Realloc @p s to append the formatted result of @p fmt and return @p
1606   s, which may have moved.  Good for gradually accumulating output
1607   into a string buffer.
1608  */
1609 char *talloc_asprintf_append(char *s, const char *fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
1610 {
1611         va_list ap;
1612 
1613         va_start(ap, fmt);
1614         s = talloc_vasprintf_append(s, fmt, ap);
1615         va_end(ap);
1616         return s;
1617 }
1618 
1619 /*
1620   Realloc @p s to append the formatted result of @p fmt and return @p
1621   s, which may have moved.  Good for gradually accumulating output
1622   into a buffer.
1623  */
1624 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
1625 {
1626         va_list ap;
1627 
1628         va_start(ap, fmt);
1629         s = talloc_vasprintf_append_buffer(s, fmt, ap);
1630         va_end(ap);
1631         return s;
1632 }
1633 
1634 /*
1635   alloc an array, checking for integer overflow in the array size
1636 */
1637 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1638 {
1639         if (count >= MAX_TALLOC_SIZE/el_size) {
1640                 return NULL;
1641         }
1642         return _talloc_named_const(ctx, el_size * count, name);
1643 }
1644 
1645 /*
1646   alloc an zero array, checking for integer overflow in the array size
1647 */
1648 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1649 {
1650         if (count >= MAX_TALLOC_SIZE/el_size) {
1651                 return NULL;
1652         }
1653         return _talloc_zero(ctx, el_size * count, name);
1654 }
1655 
1656 /*
1657   realloc an array, checking for integer overflow in the array size
1658 */
1659 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1660 {
1661         if (count >= MAX_TALLOC_SIZE/el_size) {
1662                 return NULL;
1663         }
1664         return _talloc_realloc(ctx, ptr, el_size * count, name);
1665 }
1666 
1667 /*
1668   a function version of talloc_realloc(), so it can be passed as a function pointer
1669   to libraries that want a realloc function (a realloc function encapsulates
1670   all the basic capabilities of an allocation library, which is why this is useful)
1671 */
1672 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1673 {
1674         return _talloc_realloc(context, ptr, size, NULL);
1675 }
1676 
1677 
1678 static int talloc_autofree_destructor(void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
1679 {
1680         autofree_context = NULL;
1681         return 0;
1682 }
1683 
1684 static void talloc_autofree(void)
     /* [<][>][^][v][top][bottom][index][help] */
1685 {
1686         _talloc_free(autofree_context);
1687 }
1688 
1689 /*
1690   return a context which will be auto-freed on exit
1691   this is useful for reducing the noise in leak reports
1692 */
1693 void *talloc_autofree_context(void)
     /* [<][>][^][v][top][bottom][index][help] */
1694 {
1695         if (autofree_context == NULL) {
1696                 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
1697                 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
1698                 atexit(talloc_autofree);
1699         }
1700         return autofree_context;
1701 }
1702 
1703 size_t talloc_get_size(const void *context)
     /* [<][>][^][v][top][bottom][index][help] */
1704 {
1705         struct talloc_chunk *tc;
1706 
1707         if (context == NULL)
1708                 return 0;
1709 
1710         tc = talloc_chunk_from_ptr(context);
1711 
1712         return tc->size;
1713 }
1714 
1715 /*
1716   find a parent of this context that has the given name, if any
1717 */
1718 void *talloc_find_parent_byname(const void *context, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1719 {
1720         struct talloc_chunk *tc;
1721 
1722         if (context == NULL) {
1723                 return NULL;
1724         }
1725 
1726         tc = talloc_chunk_from_ptr(context);
1727         while (tc) {
1728                 if (tc->name && strcmp(tc->name, name) == 0) {
1729                         return TC_PTR_FROM_CHUNK(tc);
1730                 }
1731                 while (tc && tc->prev) tc = tc->prev;
1732                 if (tc) {
1733                         tc = tc->parent;
1734                 }
1735         }
1736         return NULL;
1737 }
1738 
1739 /*
1740   show the parentage of a context
1741 */
1742 void talloc_show_parents(const void *context, FILE *file)
     /* [<][>][^][v][top][bottom][index][help] */
1743 {
1744         struct talloc_chunk *tc;
1745 
1746         if (context == NULL) {
1747                 fprintf(file, "talloc no parents for NULL\n");
1748                 return;
1749         }
1750 
1751         tc = talloc_chunk_from_ptr(context);
1752         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1753         while (tc) {
1754                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1755                 while (tc && tc->prev) tc = tc->prev;
1756                 if (tc) {
1757                         tc = tc->parent;
1758                 }
1759         }
1760         fflush(file);
1761 }
1762 
1763 /*
1764   return 1 if ptr is a parent of context
1765 */
1766 int talloc_is_parent(const void *context, const void *ptr)
     /* [<][>][^][v][top][bottom][index][help] */
1767 {
1768         struct talloc_chunk *tc;
1769 
1770         if (context == NULL) {
1771                 return 0;
1772         }
1773 
1774         tc = talloc_chunk_from_ptr(context);
1775         while (tc) {
1776                 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1777                 while (tc && tc->prev) tc = tc->prev;
1778                 if (tc) {
1779                         tc = tc->parent;
1780                 }
1781         }
1782         return 0;
1783 }

/* [<][>][^][v][top][bottom][index][help] */