samba-gpupdate: Test that sysvol paths download in case-insensitive way
[Samba.git] / lib / util / talloc_report.c
blob0aec96603b62fcb2fc543125296a6f9400f2460b
1 /*
2 * talloc_report into a string
4 * Copyright Volker Lendecke <vl@samba.org> 2015
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "replace.h"
21 #include "talloc_report.h"
24 * talloc_vasprintf into a buffer that doubles its size. The real string
25 * length is maintained in "pstr_len".
28 static char *talloc_vasprintf_append_largebuf(char *buf, ssize_t *pstr_len,
29 const char *fmt, va_list ap)
30 PRINTF_ATTRIBUTE(3,0);
32 static char *talloc_vasprintf_append_largebuf(char *buf, ssize_t *pstr_len,
33 const char *fmt, va_list ap)
35 ssize_t str_len = *pstr_len;
36 size_t buflen, needed, space = 0;
37 char *start = NULL, *tmpbuf = NULL;
38 va_list ap2;
39 int printlen;
41 if (str_len == -1) {
42 return NULL;
44 if (buf == NULL) {
45 return NULL;
47 if (fmt == NULL) {
48 return NULL;
50 buflen = talloc_get_size(buf);
52 if (buflen > (size_t)str_len) {
53 start = buf + str_len;
54 space = buflen - str_len;
55 } else {
56 return NULL;
59 va_copy(ap2, ap);
60 printlen = vsnprintf(start, space, fmt, ap2);
61 va_end(ap2);
63 if (printlen < 0) {
64 goto fail;
67 needed = str_len + printlen + 1;
69 if (needed > buflen) {
70 buflen = MAX(128, buflen);
72 while (buflen < needed) {
73 buflen *= 2;
76 tmpbuf = talloc_realloc(NULL, buf, char, buflen);
77 if (tmpbuf == NULL) {
78 goto fail;
80 buf = tmpbuf;
82 va_copy(ap2, ap);
83 vsnprintf(buf + str_len, buflen - str_len, fmt, ap2);
84 va_end(ap2);
86 *pstr_len = (needed - 1);
87 return buf;
88 fail:
89 *pstr_len = -1;
90 return buf;
93 static char *talloc_asprintf_append_largebuf(char *buf, ssize_t *pstr_len,
94 const char *fmt, ...)
95 PRINTF_ATTRIBUTE(3,4);
97 static char *talloc_asprintf_append_largebuf(char *buf, ssize_t *pstr_len,
98 const char *fmt, ...)
100 va_list ap;
102 va_start(ap, fmt);
103 buf = talloc_vasprintf_append_largebuf(buf, pstr_len, fmt, ap);
104 va_end(ap);
105 return buf;
108 struct talloc_report_str_state {
109 ssize_t str_len;
110 char *s;
113 static void talloc_report_str_helper(const void *ptr, int depth, int max_depth,
114 int is_ref, void *private_data)
116 struct talloc_report_str_state *state = private_data;
117 const char *name = talloc_get_name(ptr);
119 if (ptr == state->s) {
120 return;
123 if (is_ref) {
124 state->s = talloc_asprintf_append_largebuf(
125 state->s, &state->str_len,
126 "%*sreference to: %s\n", depth*4, "", name);
127 return;
130 if (depth == 0) {
131 state->s = talloc_asprintf_append_largebuf(
132 state->s, &state->str_len,
133 "%stalloc report on '%s' "
134 "(total %6lu bytes in %3lu blocks)\n",
135 (max_depth < 0 ? "full " :""), name,
136 (unsigned long)talloc_total_size(ptr),
137 (unsigned long)talloc_total_blocks(ptr));
138 return;
141 if (strcmp(name, "char") == 0) {
143 * Print out the first 50 bytes of the string
145 state->s = talloc_asprintf_append_largebuf(
146 state->s, &state->str_len,
147 "%*s%-30s contains %6lu bytes in %3lu blocks "
148 "(ref %zu): %*s\n", depth*4, "", name,
149 (unsigned long)talloc_total_size(ptr),
150 (unsigned long)talloc_total_blocks(ptr),
151 talloc_reference_count(ptr),
152 (int)MIN(50, talloc_get_size(ptr)),
153 (const char *)ptr);
154 return;
157 state->s = talloc_asprintf_append_largebuf(
158 state->s, &state->str_len,
159 "%*s%-30s contains %6lu bytes in %3lu blocks (ref %zu) %p\n",
160 depth*4, "", name,
161 (unsigned long)talloc_total_size(ptr),
162 (unsigned long)talloc_total_blocks(ptr),
163 talloc_reference_count(ptr), ptr);
166 char *talloc_report_str(TALLOC_CTX *mem_ctx, TALLOC_CTX *root)
168 struct talloc_report_str_state state;
170 state.s = talloc_strdup(mem_ctx, "");
171 if (state.s == NULL) {
172 return NULL;
174 state.str_len = 0;
176 talloc_report_depth_cb(root, 0, -1, talloc_report_str_helper, &state);
178 if (state.str_len == -1) {
179 talloc_free(state.s);
180 return NULL;
183 return talloc_realloc(mem_ctx, state.s, char, state.str_len+1);