~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to lib/talloc/talloc.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
#endif
46
46
#endif
47
47
 
 
48
/* Special macros that are no-ops except when run under Valgrind on
 
49
 * x86.  They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
 
50
#ifdef HAVE_VALGRIND_MEMCHECK_H
 
51
        /* memcheck.h includes valgrind.h */
 
52
#include <valgrind/memcheck.h>
 
53
#elif defined(HAVE_VALGRIND_H)
 
54
#include <valgrind.h>
 
55
#endif
 
56
 
48
57
/* use this to force every realloc to change the pointer, to stress test
49
58
   code that might not cope */
50
59
#define ALWAYS_REALLOC 0
104
113
static void *null_context;
105
114
static void *autofree_context;
106
115
 
 
116
/* used to enable fill of memory on free, which can be useful for
 
117
 * catching use after free errors when valgrind is too slow
 
118
 */
 
119
static struct {
 
120
        bool initialised;
 
121
        bool enabled;
 
122
        uint8_t fill_value;
 
123
} talloc_fill;
 
124
 
 
125
#define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
 
126
 
 
127
/*
 
128
 * do not wipe the header, to allow the
 
129
 * double-free logic to still work
 
130
 */
 
131
#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
 
132
        if (unlikely(talloc_fill.enabled)) { \
 
133
                size_t _flen = (_tc)->size; \
 
134
                char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
 
135
                memset(_fptr, talloc_fill.fill_value, _flen); \
 
136
        } \
 
137
} while (0)
 
138
 
 
139
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
 
140
/* Mark the whole chunk as not accessable */
 
141
#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
 
142
        size_t _flen = TC_HDR_SIZE + (_tc)->size; \
 
143
        char *_fptr = (char *)(_tc); \
 
144
        VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
 
145
} while(0)
 
146
#else
 
147
#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
 
148
#endif
 
149
 
 
150
#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
 
151
        TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
 
152
        TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
 
153
} while (0)
 
154
 
 
155
#define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
 
156
        if (unlikely(talloc_fill.enabled)) { \
 
157
                size_t _flen = (_tc)->size - (_new_size); \
 
158
                char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
 
159
                _fptr += (_new_size); \
 
160
                memset(_fptr, talloc_fill.fill_value, _flen); \
 
161
        } \
 
162
} while (0)
 
163
 
 
164
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
 
165
/* Mark the unused bytes not accessable */
 
166
#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
 
167
        size_t _flen = (_tc)->size - (_new_size); \
 
168
        char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
 
169
        _fptr += (_new_size); \
 
170
        VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
 
171
} while (0)
 
172
#else
 
173
#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
 
174
#endif
 
175
 
 
176
#define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
 
177
        TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
 
178
        TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
 
179
} while (0)
 
180
 
 
181
#define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
 
182
        if (unlikely(talloc_fill.enabled)) { \
 
183
                size_t _flen = (_tc)->size - (_new_size); \
 
184
                char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
 
185
                _fptr += (_new_size); \
 
186
                memset(_fptr, talloc_fill.fill_value, _flen); \
 
187
        } \
 
188
} while (0)
 
189
 
 
190
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
 
191
/* Mark the unused bytes as undefined */
 
192
#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
 
193
        size_t _flen = (_tc)->size - (_new_size); \
 
194
        char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
 
195
        _fptr += (_new_size); \
 
196
        VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
 
197
} while (0)
 
198
#else
 
199
#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
 
200
#endif
 
201
 
 
202
#define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
 
203
        TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
 
204
        TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
 
205
} while (0)
 
206
 
 
207
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
 
208
/* Mark the new bytes as undefined */
 
209
#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
 
210
        size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
 
211
        size_t _new_used = TC_HDR_SIZE + (_new_size); \
 
212
        size_t _flen = _new_used - _old_used; \
 
213
        char *_fptr = _old_used + (char *)(_tc); \
 
214
        VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
 
215
} while (0)
 
216
#else
 
217
#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
 
218
#endif
 
219
 
 
220
#define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
 
221
        TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
 
222
} while (0)
 
223
 
107
224
struct talloc_reference_handle {
108
225
        struct talloc_reference_handle *next, *prev;
109
226
        void *ptr;
136
253
};
137
254
 
138
255
/* 16 byte alignment seems to keep everyone happy */
139
 
#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
 
256
#define TC_ALIGN16(s) (((s)+15)&~15)
 
257
#define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
140
258
#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
141
259
 
142
 
int talloc_version_major(void)
 
260
_PUBLIC_ int talloc_version_major(void)
143
261
{
144
262
        return TALLOC_VERSION_MAJOR;
145
263
}
146
264
 
147
 
int talloc_version_minor(void)
 
265
_PUBLIC_ int talloc_version_minor(void)
148
266
{
149
267
        return TALLOC_VERSION_MINOR;
150
268
}
151
269
 
152
270
static void (*talloc_log_fn)(const char *message);
153
271
 
154
 
void talloc_set_log_fn(void (*log_fn)(const char *message))
 
272
_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
155
273
{
156
274
        talloc_log_fn = log_fn;
157
275
}
179
297
        fprintf(stderr, "%s", message);
180
298
}
181
299
 
182
 
void talloc_set_log_stderr(void)
 
300
_PUBLIC_ void talloc_set_log_stderr(void)
183
301
{
184
302
        talloc_set_log_fn(talloc_log_stderr);
185
303
}
186
304
 
187
305
static void (*talloc_abort_fn)(const char *reason);
188
306
 
189
 
void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
 
307
_PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
190
308
{
191
309
        talloc_abort_fn = abort_fn;
192
310
}
213
331
        talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
214
332
}
215
333
 
216
 
static void talloc_abort_double_free(void)
 
334
static void talloc_abort_access_after_free(void)
217
335
{
218
 
        talloc_abort("Bad talloc magic value - double free");
 
336
        talloc_abort("Bad talloc magic value - access after free");
219
337
}
220
338
 
221
339
static void talloc_abort_unknown_value(void)
235
353
                }
236
354
 
237
355
                if (tc->flags & TALLOC_FLAG_FREE) {
238
 
                        talloc_log("talloc: double free error - first free may be at %s\n", tc->name);
239
 
                        talloc_abort_double_free();
 
356
                        talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
 
357
                        talloc_abort_access_after_free();
240
358
                        return NULL;
241
359
                } else {
242
360
                        talloc_abort_unknown_value();
291
409
        return tc->parent;
292
410
}
293
411
 
294
 
void *talloc_parent(const void *ptr)
 
412
_PUBLIC_ void *talloc_parent(const void *ptr)
295
413
{
296
414
        struct talloc_chunk *tc = talloc_parent_chunk(ptr);
297
415
        return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
300
418
/*
301
419
  find parents name
302
420
*/
303
 
const char *talloc_parent_name(const void *ptr)
 
421
_PUBLIC_ const char *talloc_parent_name(const void *ptr)
304
422
{
305
423
        struct talloc_chunk *tc = talloc_parent_chunk(ptr);
306
424
        return tc? tc->name : NULL;
321
439
 
322
440
#define TALLOC_POOL_HDR_SIZE 16
323
441
 
 
442
#define TC_POOL_SPACE_LEFT(_pool_tc) \
 
443
        PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \
 
444
                 (_pool_tc)->pool)
 
445
 
 
446
#define TC_POOL_FIRST_CHUNK(_pool_tc) \
 
447
        ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc)))
 
448
 
 
449
#define TC_POOLMEM_CHUNK_SIZE(_tc) \
 
450
        TC_ALIGN16(TC_HDR_SIZE + (_tc)->size)
 
451
 
 
452
#define TC_POOLMEM_NEXT_CHUNK(_tc) \
 
453
        ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc)))
 
454
 
 
455
/* Mark the whole remaining pool as not accessable */
 
456
#define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \
 
457
        if (unlikely(talloc_fill.enabled)) { \
 
458
                size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
 
459
                char *_fptr = (char *)(_pool_tc)->pool; \
 
460
                memset(_fptr, talloc_fill.fill_value, _flen); \
 
461
        } \
 
462
} while(0)
 
463
 
 
464
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
 
465
/* Mark the whole remaining pool as not accessable */
 
466
#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \
 
467
        size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
 
468
        char *_fptr = (char *)(_pool_tc)->pool; \
 
469
        VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
 
470
} while(0)
 
471
#else
 
472
#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0)
 
473
#endif
 
474
 
 
475
#define TC_INVALIDATE_POOL(_pool_tc) do { \
 
476
        TC_INVALIDATE_FILL_POOL(_pool_tc); \
 
477
        TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \
 
478
} while (0)
 
479
 
324
480
static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
325
481
{
326
 
        return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
 
482
        return (unsigned int *)((char *)tc + TC_HDR_SIZE);
327
483
}
328
484
 
329
485
/*
353
509
                return NULL;
354
510
        }
355
511
 
356
 
        space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
357
 
                - ((char *)pool_ctx->pool);
 
512
        space_left = TC_POOL_SPACE_LEFT(pool_ctx);
358
513
 
359
514
        /*
360
515
         * Align size to 16 bytes
361
516
         */
362
 
        chunk_size = ((size + 15) & ~15);
 
517
        chunk_size = TC_ALIGN16(size);
363
518
 
364
519
        if (space_left < chunk_size) {
365
520
                return NULL;
438
593
 * Create a talloc pool
439
594
 */
440
595
 
441
 
void *talloc_pool(const void *context, size_t size)
 
596
_PUBLIC_ void *talloc_pool(const void *context, size_t size)
442
597
{
443
598
        void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
444
599
        struct talloc_chunk *tc;
450
605
        tc = talloc_chunk_from_ptr(result);
451
606
 
452
607
        tc->flags |= TALLOC_FLAG_POOL;
453
 
        tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
 
608
        tc->pool = TC_POOL_FIRST_CHUNK(tc);
454
609
 
455
610
        *talloc_pool_objectcount(tc) = 1;
456
611
 
457
 
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
458
 
        VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
459
 
#endif
 
612
        TC_INVALIDATE_POOL(tc);
460
613
 
461
614
        return result;
462
615
}
467
620
  if the destructor fails then the free is failed, and the memory can
468
621
  be continued to be used
469
622
*/
470
 
void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
 
623
_PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
471
624
{
472
625
        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
473
626
        tc->destructor = destructor;
476
629
/*
477
630
  increase the reference count on a piece of memory. 
478
631
*/
479
 
int talloc_increase_ref_count(const void *ptr)
 
632
_PUBLIC_ int talloc_increase_ref_count(const void *ptr)
480
633
{
481
634
        if (unlikely(!talloc_reference(null_context, ptr))) {
482
635
                return -1;
532
685
  same underlying data, and you want to be able to free the two instances separately,
533
686
  and in either order
534
687
*/
535
 
void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
 
688
_PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
536
689
{
537
690
        struct talloc_chunk *tc;
538
691
        struct talloc_reference_handle *handle;
556
709
 
557
710
static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
558
711
 
 
712
static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
 
713
                                        const char *location)
 
714
{
 
715
        struct talloc_chunk *pool;
 
716
        void *next_tc;
 
717
        unsigned int *pool_object_count;
 
718
 
 
719
        pool = (struct talloc_chunk *)tc->pool;
 
720
        next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
 
721
 
 
722
        tc->flags |= TALLOC_FLAG_FREE;
 
723
 
 
724
        /* we mark the freed memory with where we called the free
 
725
         * from. This means on a double free error we can report where
 
726
         * the first free came from
 
727
         */
 
728
        tc->name = location;
 
729
 
 
730
        TC_INVALIDATE_FULL_CHUNK(tc);
 
731
 
 
732
        pool_object_count = talloc_pool_objectcount(pool);
 
733
 
 
734
        if (unlikely(*pool_object_count == 0)) {
 
735
                talloc_abort("Pool object count zero!");
 
736
                return;
 
737
        }
 
738
 
 
739
        *pool_object_count -= 1;
 
740
 
 
741
        if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) {
 
742
                /*
 
743
                 * if there is just one object left in the pool
 
744
                 * and pool->flags does not have TALLOC_FLAG_FREE,
 
745
                 * it means this is the pool itself and
 
746
                 * the rest is available for new objects
 
747
                 * again.
 
748
                 */
 
749
                pool->pool = TC_POOL_FIRST_CHUNK(pool);
 
750
                TC_INVALIDATE_POOL(pool);
 
751
        } else if (unlikely(*pool_object_count == 0)) {
 
752
                /*
 
753
                 * we mark the freed memory with where we called the free
 
754
                 * from. This means on a double free error we can report where
 
755
                 * the first free came from
 
756
                 */
 
757
                pool->name = location;
 
758
 
 
759
                TC_INVALIDATE_FULL_CHUNK(pool);
 
760
                free(pool);
 
761
        } else if (pool->pool == next_tc) {
 
762
                /*
 
763
                 * if pool->pool still points to end of
 
764
                 * 'tc' (which is stored in the 'next_tc' variable),
 
765
                 * we can reclaim the memory of 'tc'.
 
766
                 */
 
767
                pool->pool = tc;
 
768
        }
 
769
}
 
770
 
 
771
static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
 
772
                                                  void *ptr,
 
773
                                                  const char *location);
 
774
 
559
775
/* 
560
776
   internal talloc_free call
561
777
*/
567
783
                return -1;
568
784
        }
569
785
 
 
786
        /* possibly initialised the talloc fill value */
 
787
        if (unlikely(!talloc_fill.initialised)) {
 
788
                const char *fill = getenv(TALLOC_FILL_ENV);
 
789
                if (fill != NULL) {
 
790
                        talloc_fill.enabled = true;
 
791
                        talloc_fill.fill_value = strtoul(fill, NULL, 0);
 
792
                }
 
793
                talloc_fill.initialised = true;
 
794
        }
 
795
 
570
796
        tc = talloc_chunk_from_ptr(ptr);
571
797
 
572
798
        if (unlikely(tc->refs)) {
573
799
                int is_child;
574
 
                /* check this is a reference from a child or grantchild
575
 
                 * back to it's parent or grantparent
 
800
                /* check if this is a reference from a child or
 
801
                 * grandchild back to it's parent or grandparent
576
802
                 *
577
803
                 * in that case we need to remove the reference and
578
804
                 * call another instance of talloc_free() on the current
612
838
        } else {
613
839
                if (tc->prev) tc->prev->next = tc->next;
614
840
                if (tc->next) tc->next->prev = tc->prev;
 
841
                tc->prev = tc->next = NULL;
615
842
        }
616
843
 
617
844
        tc->flags |= TALLOC_FLAG_LOOP;
618
845
 
619
 
        while (tc->child) {
620
 
                /* we need to work out who will own an abandoned child
621
 
                   if it cannot be freed. In priority order, the first
622
 
                   choice is owner of any remaining reference to this
623
 
                   pointer, the second choice is our parent, and the
624
 
                   final choice is the null context. */
625
 
                void *child = TC_PTR_FROM_CHUNK(tc->child);
626
 
                const void *new_parent = null_context;
627
 
                if (unlikely(tc->child->refs)) {
628
 
                        struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
629
 
                        if (p) new_parent = TC_PTR_FROM_CHUNK(p);
630
 
                }
631
 
                if (unlikely(_talloc_free_internal(child, location) == -1)) {
632
 
                        if (new_parent == null_context) {
633
 
                                struct talloc_chunk *p = talloc_parent_chunk(ptr);
634
 
                                if (p) new_parent = TC_PTR_FROM_CHUNK(p);
635
 
                        }
636
 
                        _talloc_steal_internal(new_parent, child);
637
 
                }
638
 
        }
 
846
        _talloc_free_children_internal(tc, ptr, location);
639
847
 
640
848
        tc->flags |= TALLOC_FLAG_FREE;
641
849
 
645
853
         */      
646
854
        tc->name = location;
647
855
 
648
 
        if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
649
 
                struct talloc_chunk *pool;
 
856
        if (tc->flags & TALLOC_FLAG_POOL) {
650
857
                unsigned int *pool_object_count;
651
858
 
652
 
                pool = (tc->flags & TALLOC_FLAG_POOL)
653
 
                        ? tc : (struct talloc_chunk *)tc->pool;
654
 
 
655
 
                pool_object_count = talloc_pool_objectcount(pool);
656
 
 
657
 
                if (*pool_object_count == 0) {
 
859
                pool_object_count = talloc_pool_objectcount(tc);
 
860
 
 
861
                if (unlikely(*pool_object_count == 0)) {
658
862
                        talloc_abort("Pool object count zero!");
659
863
                        return 0;
660
864
                }
661
865
 
662
866
                *pool_object_count -= 1;
663
867
 
664
 
                if (*pool_object_count == 0) {
665
 
                        free(pool);
 
868
                if (unlikely(*pool_object_count == 0)) {
 
869
                        TC_INVALIDATE_FULL_CHUNK(tc);
 
870
                        free(tc);
666
871
                }
667
 
        }
668
 
        else {
 
872
        } else if (tc->flags & TALLOC_FLAG_POOLMEM) {
 
873
                _talloc_free_poolmem(tc, location);
 
874
        } else {
 
875
                TC_INVALIDATE_FULL_CHUNK(tc);
669
876
                free(tc);
670
877
        }
671
878
        return 0;
719
926
        } else {
720
927
                if (tc->prev) tc->prev->next = tc->next;
721
928
                if (tc->next) tc->next->prev = tc->prev;
 
929
                tc->prev = tc->next = NULL;
722
930
        }
723
931
 
724
932
        tc->parent = new_tc;
733
941
   ptr on success, or NULL if it could not be transferred.
734
942
   passing NULL as ptr will always return NULL with no side effects.
735
943
*/
736
 
void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
 
944
_PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
737
945
{
738
946
        struct talloc_chunk *tc;
739
947
 
754
962
                                   h->location);
755
963
                }
756
964
        }
 
965
 
 
966
#if 0
 
967
        /* this test is probably too expensive to have on in the
 
968
           normal build, but it useful for debugging */
 
969
        if (talloc_is_parent(new_ctx, ptr)) {
 
970
                talloc_log("WARNING: stealing into talloc child at %s\n", location);
 
971
        }
 
972
#endif
757
973
        
758
974
        return _talloc_steal_internal(new_ctx, ptr);
759
975
}
765
981
 
766
982
   The old parent can be either a reference or a parent
767
983
*/
768
 
void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
 
984
_PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
769
985
{
770
986
        struct talloc_chunk *tc;
771
987
        struct talloc_reference_handle *h;
825
1041
  remove a specific parent context from a pointer. This is a more
826
1042
  controlled varient of talloc_free()
827
1043
*/
828
 
int talloc_unlink(const void *context, void *ptr)
 
1044
_PUBLIC_ int talloc_unlink(const void *context, void *ptr)
829
1045
{
830
1046
        struct talloc_chunk *tc_p, *new_p;
831
1047
        void *new_parent;
892
1108
/*
893
1109
  add a name to an existing pointer
894
1110
*/
895
 
const char *talloc_set_name(const void *ptr, const char *fmt, ...)
 
1111
_PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
896
1112
{
897
1113
        const char *name;
898
1114
        va_list ap;
908
1124
  talloc_named() operates just like talloc() except that it allows you
909
1125
  to name the pointer.
910
1126
*/
911
 
void *talloc_named(const void *context, size_t size, const char *fmt, ...)
 
1127
_PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
912
1128
{
913
1129
        va_list ap;
914
1130
        void *ptr;
932
1148
/*
933
1149
  return the name of a talloc ptr, or "UNNAMED"
934
1150
*/
935
 
const char *talloc_get_name(const void *ptr)
 
1151
_PUBLIC_ const char *talloc_get_name(const void *ptr)
936
1152
{
937
1153
        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
938
1154
        if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
949
1165
  check if a pointer has the given name. If it does, return the pointer,
950
1166
  otherwise return NULL
951
1167
*/
952
 
void *talloc_check_name(const void *ptr, const char *name)
 
1168
_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
953
1169
{
954
1170
        const char *pname;
955
1171
        if (unlikely(ptr == NULL)) return NULL;
978
1194
        talloc_abort(reason);
979
1195
}
980
1196
 
981
 
void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
 
1197
_PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
982
1198
{
983
1199
        const char *pname;
984
1200
 
999
1215
/*
1000
1216
  this is for compatibility with older versions of talloc
1001
1217
*/
1002
 
void *talloc_init(const char *fmt, ...)
 
1218
_PUBLIC_ void *talloc_init(const char *fmt, ...)
1003
1219
{
1004
1220
        va_list ap;
1005
1221
        void *ptr;
1006
1222
        const char *name;
1007
1223
 
1008
 
        /*
1009
 
         * samba3 expects talloc_report_depth_cb(NULL, ...)
1010
 
         * reports all talloc'ed memory, so we need to enable
1011
 
         * null_tracking
1012
 
         */
1013
 
        talloc_enable_null_tracking();
1014
 
 
1015
1224
        ptr = __talloc(NULL, 0);
1016
1225
        if (unlikely(ptr == NULL)) return NULL;
1017
1226
 
1027
1236
        return ptr;
1028
1237
}
1029
1238
 
 
1239
static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
 
1240
                                                  void *ptr,
 
1241
                                                  const char *location)
 
1242
{
 
1243
        while (tc->child) {
 
1244
                /* we need to work out who will own an abandoned child
 
1245
                   if it cannot be freed. In priority order, the first
 
1246
                   choice is owner of any remaining reference to this
 
1247
                   pointer, the second choice is our parent, and the
 
1248
                   final choice is the null context. */
 
1249
                void *child = TC_PTR_FROM_CHUNK(tc->child);
 
1250
                const void *new_parent = null_context;
 
1251
                struct talloc_chunk *old_parent = NULL;
 
1252
                if (unlikely(tc->child->refs)) {
 
1253
                        struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
 
1254
                        if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 
1255
                }
 
1256
                if (unlikely(_talloc_free_internal(child, location) == -1)) {
 
1257
                        if (new_parent == null_context) {
 
1258
                                struct talloc_chunk *p = talloc_parent_chunk(ptr);
 
1259
                                if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 
1260
                        }
 
1261
                        _talloc_steal_internal(new_parent, child);
 
1262
                }
 
1263
        }
 
1264
}
 
1265
 
1030
1266
/*
1031
1267
  this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1032
1268
  should probably not be used in new code. It's in here to keep the talloc
1033
1269
  code consistent across Samba 3 and 4.
1034
1270
*/
1035
 
void talloc_free_children(void *ptr)
 
1271
_PUBLIC_ void talloc_free_children(void *ptr)
1036
1272
{
 
1273
        struct talloc_chunk *tc_name = NULL;
1037
1274
        struct talloc_chunk *tc;
1038
1275
 
1039
1276
        if (unlikely(ptr == NULL)) {
1042
1279
 
1043
1280
        tc = talloc_chunk_from_ptr(ptr);
1044
1281
 
1045
 
        while (tc->child) {
1046
 
                /* we need to work out who will own an abandoned child
1047
 
                   if it cannot be freed. In priority order, the first
1048
 
                   choice is owner of any remaining reference to this
1049
 
                   pointer, the second choice is our parent, and the
1050
 
                   final choice is the null context. */
1051
 
                void *child = TC_PTR_FROM_CHUNK(tc->child);
1052
 
                const void *new_parent = null_context;
1053
 
                if (unlikely(tc->child->refs)) {
1054
 
                        struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1055
 
                        if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 
1282
        /* we do not want to free the context name if it is a child .. */
 
1283
        if (likely(tc->child)) {
 
1284
                for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
 
1285
                        if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1056
1286
                }
1057
 
                if (unlikely(talloc_free(child) == -1)) {
1058
 
                        if (new_parent == null_context) {
1059
 
                                struct talloc_chunk *p = talloc_parent_chunk(ptr);
1060
 
                                if (p) new_parent = TC_PTR_FROM_CHUNK(p);
 
1287
                if (tc_name) {
 
1288
                        _TLIST_REMOVE(tc->child, tc_name);
 
1289
                        if (tc->child) {
 
1290
                                tc->child->parent = tc;
1061
1291
                        }
1062
 
                        _talloc_steal_internal(new_parent, child);
1063
1292
                }
1064
1293
        }
1065
1294
 
1066
 
        if ((tc->flags & TALLOC_FLAG_POOL)
1067
 
            && (*talloc_pool_objectcount(tc) == 1)) {
1068
 
                tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
1069
 
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
1070
 
                VALGRIND_MAKE_MEM_NOACCESS(
1071
 
                        tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
1072
 
#endif
 
1295
        _talloc_free_children_internal(tc, ptr, __location__);
 
1296
 
 
1297
        /* .. so we put it back after all other children have been freed */
 
1298
        if (tc_name) {
 
1299
                if (tc->child) {
 
1300
                        tc->child->parent = NULL;
 
1301
                }
 
1302
                tc_name->parent = tc;
 
1303
                _TLIST_ADD(tc->child, tc_name);
1073
1304
        }
1074
1305
}
1075
1306
 
1076
1307
/* 
1077
1308
   Allocate a bit of memory as a child of an existing pointer
1078
1309
*/
1079
 
void *_talloc(const void *context, size_t size)
 
1310
_PUBLIC_ void *_talloc(const void *context, size_t size)
1080
1311
{
1081
1312
        return __talloc(context, size);
1082
1313
}
1084
1315
/*
1085
1316
  externally callable talloc_set_name_const()
1086
1317
*/
1087
 
void talloc_set_name_const(const void *ptr, const char *name)
 
1318
_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1088
1319
{
1089
1320
        _talloc_set_name_const(ptr, name);
1090
1321
}
1094
1325
  talloc_named() operates just like talloc() except that it allows you
1095
1326
  to name the pointer.
1096
1327
*/
1097
 
void *talloc_named_const(const void *context, size_t size, const char *name)
 
1328
_PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1098
1329
{
1099
1330
        return _talloc_named_const(context, size, name);
1100
1331
}
1107
1338
   will not be freed if the ref_count is > 1 or the destructor (if
1108
1339
   any) returns non-zero
1109
1340
*/
1110
 
int _talloc_free(void *ptr, const char *location)
 
1341
_PUBLIC_ int _talloc_free(void *ptr, const char *location)
1111
1342
{
1112
1343
        struct talloc_chunk *tc;
1113
1344
 
1120
1351
        if (unlikely(tc->refs != NULL)) {
1121
1352
                struct talloc_reference_handle *h;
1122
1353
 
 
1354
                if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
 
1355
                        /* in this case we do know which parent should
 
1356
                           get this pointer, as there is really only
 
1357
                           one parent */
 
1358
                        return talloc_unlink(null_context, ptr);
 
1359
                }
 
1360
 
1123
1361
                talloc_log("ERROR: talloc_free with references at %s\n",
1124
1362
                           location);
1125
1363
 
1139
1377
  A talloc version of realloc. The context argument is only used if
1140
1378
  ptr is NULL
1141
1379
*/
1142
 
void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
 
1380
_PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1143
1381
{
1144
1382
        struct talloc_chunk *tc;
1145
1383
        void *new_ptr;
1146
1384
        bool malloced = false;
 
1385
        struct talloc_chunk *pool_tc = NULL;
1147
1386
 
1148
1387
        /* size zero is equivalent to free() */
1149
1388
        if (unlikely(size == 0)) {
1172
1411
                return NULL;
1173
1412
        }
1174
1413
 
 
1414
        /* don't let anybody try to realloc a talloc_pool */
 
1415
        if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
 
1416
                pool_tc = (struct talloc_chunk *)tc->pool;
 
1417
        }
 
1418
 
 
1419
#if (ALWAYS_REALLOC == 0)
1175
1420
        /* don't shrink if we have less than 1k to gain */
1176
 
        if ((size < tc->size) && ((tc->size - size) < 1024)) {
1177
 
                tc->size = size;
 
1421
        if (size < tc->size) {
 
1422
                if (pool_tc) {
 
1423
                        void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
 
1424
                        TC_INVALIDATE_SHRINK_CHUNK(tc, size);
 
1425
                        tc->size = size;
 
1426
                        if (next_tc == pool_tc->pool) {
 
1427
                                pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
 
1428
                        }
 
1429
                        return ptr;
 
1430
                } else if ((tc->size - size) < 1024) {
 
1431
                        /*
 
1432
                         * if we call TC_INVALIDATE_SHRINK_CHUNK() here
 
1433
                         * we would need to call TC_UNDEFINE_GROW_CHUNK()
 
1434
                         * after each realloc call, which slows down
 
1435
                         * testing a lot :-(.
 
1436
                         *
 
1437
                         * That is why we only mark memory as undefined here.
 
1438
                         */
 
1439
                        TC_UNDEFINE_SHRINK_CHUNK(tc, size);
 
1440
 
 
1441
                        /* do not shrink if we have less than 1k to gain */
 
1442
                        tc->size = size;
 
1443
                        return ptr;
 
1444
                }
 
1445
        } else if (tc->size == size) {
 
1446
                /*
 
1447
                 * do not change the pointer if it is exactly
 
1448
                 * the same size.
 
1449
                 */
1178
1450
                return ptr;
1179
1451
        }
 
1452
#endif
1180
1453
 
1181
1454
        /* by resetting magic we catch users of the old memory */
1182
1455
        tc->flags |= TALLOC_FLAG_FREE;
1183
1456
 
1184
1457
#if ALWAYS_REALLOC
1185
 
        new_ptr = malloc(size + TC_HDR_SIZE);
1186
 
        if (new_ptr) {
1187
 
                memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1188
 
                free(tc);
 
1458
        if (pool_tc) {
 
1459
                new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
 
1460
                *talloc_pool_objectcount(pool_tc) -= 1;
 
1461
 
 
1462
                if (new_ptr == NULL) {
 
1463
                        new_ptr = malloc(TC_HDR_SIZE+size);
 
1464
                        malloced = true;
 
1465
                }
 
1466
 
 
1467
                if (new_ptr) {
 
1468
                        memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
 
1469
                        TC_INVALIDATE_FULL_CHUNK(tc);
 
1470
                }
 
1471
        } else {
 
1472
                new_ptr = malloc(size + TC_HDR_SIZE);
 
1473
                if (new_ptr) {
 
1474
                        memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
 
1475
                        free(tc);
 
1476
                }
1189
1477
        }
1190
1478
#else
1191
 
        if (tc->flags & TALLOC_FLAG_POOLMEM) {
 
1479
        if (pool_tc) {
 
1480
                void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
 
1481
                size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc);
 
1482
                size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
 
1483
                size_t space_needed;
 
1484
                size_t space_left;
 
1485
                unsigned int chunk_count = *talloc_pool_objectcount(pool_tc);
 
1486
 
 
1487
                if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
 
1488
                        chunk_count -= 1;
 
1489
                }
 
1490
 
 
1491
                if (chunk_count == 1) {
 
1492
                        /*
 
1493
                         * optimize for the case where 'tc' is the only
 
1494
                         * chunk in the pool.
 
1495
                         */
 
1496
                        space_needed = new_chunk_size;
 
1497
                        space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE;
 
1498
 
 
1499
                        if (space_left >= space_needed) {
 
1500
                                size_t old_used = TC_HDR_SIZE + tc->size;
 
1501
                                size_t new_used = TC_HDR_SIZE + size;
 
1502
                                pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc);
 
1503
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
 
1504
                                /*
 
1505
                                 * we need to prepare the memmove into
 
1506
                                 * the unaccessable area.
 
1507
                                 */
 
1508
                                {
 
1509
                                        size_t diff = PTR_DIFF(tc, pool_tc->pool);
 
1510
                                        size_t flen = MIN(diff, old_used);
 
1511
                                        char *fptr = (char *)pool_tc->pool;
 
1512
                                        VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen);
 
1513
                                }
 
1514
#endif
 
1515
                                memmove(pool_tc->pool, tc, old_used);
 
1516
                                new_ptr = pool_tc->pool;
 
1517
 
 
1518
                                tc = (struct talloc_chunk *)new_ptr;
 
1519
                                TC_UNDEFINE_GROW_CHUNK(tc, size);
 
1520
 
 
1521
                                /*
 
1522
                                 * first we do not align the pool pointer
 
1523
                                 * because we want to invalidate the padding
 
1524
                                 * too.
 
1525
                                 */
 
1526
                                pool_tc->pool = new_used + (char *)new_ptr;
 
1527
                                TC_INVALIDATE_POOL(pool_tc);
 
1528
 
 
1529
                                /* now the aligned pointer */
 
1530
                                pool_tc->pool = new_chunk_size + (char *)new_ptr;
 
1531
                                goto got_new_ptr;
 
1532
                        }
 
1533
 
 
1534
                        next_tc = NULL;
 
1535
                }
 
1536
 
 
1537
                if (new_chunk_size == old_chunk_size) {
 
1538
                        TC_UNDEFINE_GROW_CHUNK(tc, size);
 
1539
                        tc->flags &= ~TALLOC_FLAG_FREE;
 
1540
                        tc->size = size;
 
1541
                        return ptr;
 
1542
                }
 
1543
 
 
1544
                if (next_tc == pool_tc->pool) {
 
1545
                        /*
 
1546
                         * optimize for the case where 'tc' is the last
 
1547
                         * chunk in the pool.
 
1548
                         */
 
1549
                        space_needed = new_chunk_size - old_chunk_size;
 
1550
                        space_left = TC_POOL_SPACE_LEFT(pool_tc);
 
1551
 
 
1552
                        if (space_left >= space_needed) {
 
1553
                                TC_UNDEFINE_GROW_CHUNK(tc, size);
 
1554
                                tc->flags &= ~TALLOC_FLAG_FREE;
 
1555
                                tc->size = size;
 
1556
                                pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
 
1557
                                return ptr;
 
1558
                        }
 
1559
                }
1192
1560
 
1193
1561
                new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1194
 
                *talloc_pool_objectcount((struct talloc_chunk *)
1195
 
                                         (tc->pool)) -= 1;
1196
1562
 
1197
1563
                if (new_ptr == NULL) {
1198
1564
                        new_ptr = malloc(TC_HDR_SIZE+size);
1201
1567
 
1202
1568
                if (new_ptr) {
1203
1569
                        memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
 
1570
 
 
1571
                        _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1204
1572
                }
1205
1573
        }
1206
1574
        else {
1207
1575
                new_ptr = realloc(tc, size + TC_HDR_SIZE);
1208
1576
        }
 
1577
got_new_ptr:
1209
1578
#endif
1210
1579
        if (unlikely(!new_ptr)) {       
1211
1580
                tc->flags &= ~TALLOC_FLAG_FREE; 
1241
1610
  a wrapper around talloc_steal() for situations where you are moving a pointer
1242
1611
  between two structures, and want the old pointer to be set to NULL
1243
1612
*/
1244
 
void *_talloc_move(const void *new_ctx, const void *_pptr)
 
1613
_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1245
1614
{
1246
1615
        const void **pptr = discard_const_p(const void *,_pptr);
1247
1616
        void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1252
1621
/*
1253
1622
  return the total size of a talloc pool (subtree)
1254
1623
*/
1255
 
size_t talloc_total_size(const void *ptr)
 
1624
_PUBLIC_ size_t talloc_total_size(const void *ptr)
1256
1625
{
1257
1626
        size_t total = 0;
1258
1627
        struct talloc_chunk *c, *tc;
1287
1656
/*
1288
1657
  return the total number of blocks in a talloc pool (subtree)
1289
1658
*/
1290
 
size_t talloc_total_blocks(const void *ptr)
 
1659
_PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1291
1660
{
1292
1661
        size_t total = 0;
1293
1662
        struct talloc_chunk *c, *tc;
1320
1689
/*
1321
1690
  return the number of external references to a pointer
1322
1691
*/
1323
 
size_t talloc_reference_count(const void *ptr)
 
1692
_PUBLIC_ size_t talloc_reference_count(const void *ptr)
1324
1693
{
1325
1694
        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1326
1695
        struct talloc_reference_handle *h;
1335
1704
/*
1336
1705
  report on memory usage by all children of a pointer, giving a full tree view
1337
1706
*/
1338
 
void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
 
1707
_PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1339
1708
                            void (*callback)(const void *ptr,
1340
1709
                                             int depth, int max_depth,
1341
1710
                                             int is_ref,
1419
1788
/*
1420
1789
  report on memory usage by all children of a pointer, giving a full tree view
1421
1790
*/
1422
 
void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
 
1791
_PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1423
1792
{
1424
1793
        if (f) {
1425
1794
                talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1430
1799
/*
1431
1800
  report on memory usage by all children of a pointer, giving a full tree view
1432
1801
*/
1433
 
void talloc_report_full(const void *ptr, FILE *f)
 
1802
_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1434
1803
{
1435
1804
        talloc_report_depth_file(ptr, 0, -1, f);
1436
1805
}
1438
1807
/*
1439
1808
  report on memory usage by all children of a pointer
1440
1809
*/
1441
 
void talloc_report(const void *ptr, FILE *f)
 
1810
_PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1442
1811
{
1443
1812
        talloc_report_depth_file(ptr, 0, 1, f);
1444
1813
}
1466
1835
/*
1467
1836
  enable tracking of the NULL context
1468
1837
*/
1469
 
void talloc_enable_null_tracking(void)
 
1838
_PUBLIC_ void talloc_enable_null_tracking(void)
1470
1839
{
1471
1840
        if (null_context == NULL) {
1472
1841
                null_context = _talloc_named_const(NULL, 0, "null_context");
1480
1849
  enable tracking of the NULL context, not moving the autofree context
1481
1850
  into the NULL context. This is needed for the talloc testsuite
1482
1851
*/
1483
 
void talloc_enable_null_tracking_no_autofree(void)
 
1852
_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
1484
1853
{
1485
1854
        if (null_context == NULL) {
1486
1855
                null_context = _talloc_named_const(NULL, 0, "null_context");
1490
1859
/*
1491
1860
  disable tracking of the NULL context
1492
1861
*/
1493
 
void talloc_disable_null_tracking(void)
 
1862
_PUBLIC_ void talloc_disable_null_tracking(void)
1494
1863
{
1495
1864
        if (null_context != NULL) {
1496
1865
                /* we have to move any children onto the real NULL
1515
1884
/*
1516
1885
  enable leak reporting on exit
1517
1886
*/
1518
 
void talloc_enable_leak_report(void)
 
1887
_PUBLIC_ void talloc_enable_leak_report(void)
1519
1888
{
1520
1889
        talloc_enable_null_tracking();
1521
1890
        atexit(talloc_report_null);
1524
1893
/*
1525
1894
  enable full leak reporting on exit
1526
1895
*/
1527
 
void talloc_enable_leak_report_full(void)
 
1896
_PUBLIC_ void talloc_enable_leak_report_full(void)
1528
1897
{
1529
1898
        talloc_enable_null_tracking();
1530
1899
        atexit(talloc_report_null_full);
1533
1902
/* 
1534
1903
   talloc and zero memory. 
1535
1904
*/
1536
 
void *_talloc_zero(const void *ctx, size_t size, const char *name)
 
1905
_PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
1537
1906
{
1538
1907
        void *p = _talloc_named_const(ctx, size, name);
1539
1908
 
1547
1916
/*
1548
1917
  memdup with a talloc. 
1549
1918
*/
1550
 
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
 
1919
_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1551
1920
{
1552
1921
        void *newp = _talloc_named_const(t, size, name);
1553
1922
 
1575
1944
/*
1576
1945
  strdup with a talloc
1577
1946
*/
1578
 
char *talloc_strdup(const void *t, const char *p)
 
1947
_PUBLIC_ char *talloc_strdup(const void *t, const char *p)
1579
1948
{
1580
1949
        if (unlikely(!p)) return NULL;
1581
1950
        return __talloc_strlendup(t, p, strlen(p));
1584
1953
/*
1585
1954
  strndup with a talloc
1586
1955
*/
1587
 
char *talloc_strndup(const void *t, const char *p, size_t n)
 
1956
_PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
1588
1957
{
1589
1958
        if (unlikely(!p)) return NULL;
1590
1959
        return __talloc_strlendup(t, p, strnlen(p, n));
1609
1978
/*
1610
1979
 * Appends at the end of the string.
1611
1980
 */
1612
 
char *talloc_strdup_append(char *s, const char *a)
 
1981
_PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
1613
1982
{
1614
1983
        if (unlikely(!s)) {
1615
1984
                return talloc_strdup(NULL, a);
1626
1995
 * Appends at the end of the talloc'ed buffer,
1627
1996
 * not the end of the string.
1628
1997
 */
1629
 
char *talloc_strdup_append_buffer(char *s, const char *a)
 
1998
_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
1630
1999
{
1631
2000
        size_t slen;
1632
2001
 
1649
2018
/*
1650
2019
 * Appends at the end of the string.
1651
2020
 */
1652
 
char *talloc_strndup_append(char *s, const char *a, size_t n)
 
2021
_PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
1653
2022
{
1654
2023
        if (unlikely(!s)) {
1655
2024
                return talloc_strdup(NULL, a);
1666
2035
 * Appends at the end of the talloc'ed buffer,
1667
2036
 * not the end of the string.
1668
2037
 */
1669
 
char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
 
2038
_PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
1670
2039
{
1671
2040
        size_t slen;
1672
2041
 
1694
2063
#endif
1695
2064
#endif
1696
2065
 
1697
 
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
 
2066
_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1698
2067
{
1699
2068
        int len;
1700
2069
        char *ret;
1725
2094
  Perform string formatting, and return a pointer to newly allocated
1726
2095
  memory holding the result, inside a memory pool.
1727
2096
 */
1728
 
char *talloc_asprintf(const void *t, const char *fmt, ...)
 
2097
_PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
1729
2098
{
1730
2099
        va_list ap;
1731
2100
        char *ret;
1778
2147
 * accumulating output into a string buffer. Appends at the end
1779
2148
 * of the string.
1780
2149
 **/
1781
 
char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
 
2150
_PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1782
2151
{
1783
2152
        if (unlikely(!s)) {
1784
2153
                return talloc_vasprintf(NULL, fmt, ap);
1792
2161
 * and return @p s, which may have moved. Always appends at the
1793
2162
 * end of the talloc'ed buffer, not the end of the string.
1794
2163
 **/
1795
 
char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
 
2164
_PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
1796
2165
{
1797
2166
        size_t slen;
1798
2167
 
1813
2182
  s, which may have moved.  Good for gradually accumulating output
1814
2183
  into a string buffer.
1815
2184
 */
1816
 
char *talloc_asprintf_append(char *s, const char *fmt, ...)
 
2185
_PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
1817
2186
{
1818
2187
        va_list ap;
1819
2188
 
1828
2197
  s, which may have moved.  Good for gradually accumulating output
1829
2198
  into a buffer.
1830
2199
 */
1831
 
char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
 
2200
_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
1832
2201
{
1833
2202
        va_list ap;
1834
2203
 
1841
2210
/*
1842
2211
  alloc an array, checking for integer overflow in the array size
1843
2212
*/
1844
 
void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
 
2213
_PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1845
2214
{
1846
2215
        if (count >= MAX_TALLOC_SIZE/el_size) {
1847
2216
                return NULL;
1852
2221
/*
1853
2222
  alloc an zero array, checking for integer overflow in the array size
1854
2223
*/
1855
 
void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
 
2224
_PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1856
2225
{
1857
2226
        if (count >= MAX_TALLOC_SIZE/el_size) {
1858
2227
                return NULL;
1863
2232
/*
1864
2233
  realloc an array, checking for integer overflow in the array size
1865
2234
*/
1866
 
void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
 
2235
_PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1867
2236
{
1868
2237
        if (count >= MAX_TALLOC_SIZE/el_size) {
1869
2238
                return NULL;
1876
2245
  to libraries that want a realloc function (a realloc function encapsulates
1877
2246
  all the basic capabilities of an allocation library, which is why this is useful)
1878
2247
*/
1879
 
void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
 
2248
_PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1880
2249
{
1881
2250
        return _talloc_realloc(context, ptr, size, NULL);
1882
2251
}
1897
2266
  return a context which will be auto-freed on exit
1898
2267
  this is useful for reducing the noise in leak reports
1899
2268
*/
1900
 
void *talloc_autofree_context(void)
 
2269
_PUBLIC_ void *talloc_autofree_context(void)
1901
2270
{
1902
2271
        if (autofree_context == NULL) {
1903
2272
                autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
1907
2276
        return autofree_context;
1908
2277
}
1909
2278
 
1910
 
size_t talloc_get_size(const void *context)
 
2279
_PUBLIC_ size_t talloc_get_size(const void *context)
1911
2280
{
1912
2281
        struct talloc_chunk *tc;
1913
2282
 
1926
2295
/*
1927
2296
  find a parent of this context that has the given name, if any
1928
2297
*/
1929
 
void *talloc_find_parent_byname(const void *context, const char *name)
 
2298
_PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
1930
2299
{
1931
2300
        struct talloc_chunk *tc;
1932
2301
 
1950
2319
/*
1951
2320
  show the parentage of a context
1952
2321
*/
1953
 
void talloc_show_parents(const void *context, FILE *file)
 
2322
_PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
1954
2323
{
1955
2324
        struct talloc_chunk *tc;
1956
2325
 
1974
2343
/*
1975
2344
  return 1 if ptr is a parent of context
1976
2345
*/
1977
 
int talloc_is_parent(const void *context, const void *ptr)
 
2346
static int _talloc_is_parent(const void *context, const void *ptr, int depth)
1978
2347
{
1979
2348
        struct talloc_chunk *tc;
1980
2349
 
1983
2352
        }
1984
2353
 
1985
2354
        tc = talloc_chunk_from_ptr(context);
1986
 
        while (tc) {
 
2355
        while (tc && depth > 0) {
1987
2356
                if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
1988
2357
                while (tc && tc->prev) tc = tc->prev;
1989
2358
                if (tc) {
1990
2359
                        tc = tc->parent;
 
2360
                        depth--;
1991
2361
                }
1992
2362
        }
1993
2363
        return 0;
1994
2364
}
 
2365
 
 
2366
/*
 
2367
  return 1 if ptr is a parent of context
 
2368
*/
 
2369
_PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
 
2370
{
 
2371
        return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
 
2372
}