~ubuntu-branches/ubuntu/wily/mpv/wily

« back to all changes in this revision

Viewing changes to talloc.c

  • Committer: Package Import Robot
  • Author(s): Alessandro Ghedini
  • Date: 2013-10-16 12:38:59 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20131016123859-wj70wr6n3mzimx3e
Tags: 0.2.0-1
* New upstream release
* Install sample configuration files as examples
* Enable Lua scripting support
* Remove copyright for talloc (not used anymore)
* Update installed docs list
* Update 01_spelling.patch
* Enable VAAPI support

Show diffs side-by-side

added added

removed removed

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