diff options
-rw-r--r-- | source3/lib/talloc/configure.ac | 2 | ||||
-rw-r--r-- | source3/lib/talloc/talloc.c | 233 | ||||
-rw-r--r-- | source3/lib/talloc/talloc.h | 26 | ||||
-rw-r--r-- | source3/lib/talloc/testsuite.c | 48 |
4 files changed, 184 insertions, 125 deletions
diff --git a/source3/lib/talloc/configure.ac b/source3/lib/talloc/configure.ac index 5f465fe93a..afc2a944f0 100644 --- a/source3/lib/talloc/configure.ac +++ b/source3/lib/talloc/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT(talloc, 1.0) +AC_INIT(talloc, 1.1.0) AC_CONFIG_SRCDIR([talloc.c]) AC_SUBST(datarootdir) AC_CONFIG_HEADER(config.h) diff --git a/source3/lib/talloc/talloc.c b/source3/lib/talloc/talloc.c index 7920a66d64..4d72c0e871 100644 --- a/source3/lib/talloc/talloc.c +++ b/source3/lib/talloc/talloc.c @@ -1109,64 +1109,132 @@ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name return newp; } +static inline char *__talloc_strlendup(const void *t, const char *p, size_t len) +{ + char *ret; + + ret = (char *)__talloc(t, len + 1); + if (unlikely(!ret)) return NULL; + + memcpy(ret, p, len); + ret[len] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + /* - strdup with a talloc + strdup with a talloc */ char *talloc_strdup(const void *t, const char *p) { + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strlen(p)); +} + +/* + strndup with a talloc +*/ +char *talloc_strndup(const void *t, const char *p, size_t n) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strnlen(p, n)); +} + +static inline char *__talloc_strlendup_append(char *s, size_t slen, + const char *a, size_t alen) +{ char *ret; - if (!p) { - return NULL; + + ret = talloc_realloc(NULL, s, char, slen + alen + 1); + if (unlikely(!ret)) return NULL; + + /* append the string and the trailing \0 */ + memcpy(&ret[slen], a, alen); + ret[slen+alen] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + * Appends at the end of the string. + */ +char *talloc_strdup_append(char *s, const char *a) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); } - ret = (char *)talloc_memdup(t, p, strlen(p) + 1); - if (likely(ret)) { - _talloc_set_name_const(ret, ret); + + if (unlikely(!a)) { + return s; } - return ret; + + return __talloc_strlendup_append(s, strlen(s), a, strlen(a)); } /* - append to a talloced string -*/ -char *talloc_append_string(const void *t, char *orig, const char *append) + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +char *talloc_strdup_append_buffer(char *s, const char *a) { - char *ret; - size_t olen = strlen(orig); - size_t alenz; + size_t slen; - if (!append) - return orig; + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } - alenz = strlen(append) + 1; + if (unlikely(!a)) { + return s; + } - ret = talloc_realloc(t, orig, char, olen + alenz); - if (!ret) - return NULL; + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } - /* append the string with the trailing \0 */ - memcpy(&ret[olen], append, alenz); + return __talloc_strlendup_append(s, slen, a, strlen(a)); +} - _talloc_set_name_const(ret, ret); +/* + * Appends at the end of the string. + */ +char *talloc_strndup_append(char *s, const char *a, size_t n) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } - return ret; + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n)); } /* - strndup with a talloc -*/ -char *talloc_strndup(const void *t, const char *p, size_t n) + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) { - size_t len; - char *ret; + size_t slen; - for (len=0; len<n && p[len]; len++) ; + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } - ret = (char *)__talloc(t, len + 1); - if (!ret) { return NULL; } - memcpy(ret, p, len); - ret[len] = 0; - _talloc_set_name_const(ret, ret); - return ret; + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strnlen(a, n)); } #ifndef HAVE_VA_COPY @@ -1188,18 +1256,18 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) va_copy(ap2, ap); len = vsnprintf(&c, 1, fmt, ap2); va_end(ap2); - if (len < 0) { + if (unlikely(len < 0)) { return NULL; } ret = (char *)__talloc(t, len+1); - if (ret) { - va_copy(ap2, ap); - vsnprintf(ret, len+1, fmt, ap2); - va_end(ap2); - _talloc_set_name_const(ret, ret); - } + if (unlikely(!ret)) return NULL; + va_copy(ap2, ap); + vsnprintf(ret, len+1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(ret, ret); return ret; } @@ -1219,30 +1287,22 @@ char *talloc_asprintf(const void *t, const char *fmt, ...) return ret; } +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) + PRINTF_ATTRIBUTE(3,0); -/** - * Realloc @p s to append the formatted result of @p fmt and @p ap, - * and return @p s, which may have moved. Good for gradually - * accumulating output into a string buffer. Appends at the end - * of the string. - **/ -char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) { - int len, s_len; + ssize_t alen; va_list ap2; char c; - if (s == NULL) { - return talloc_vasprintf(NULL, fmt, ap); - } - - s_len = strlen(s); - va_copy(ap2, ap); - len = vsnprintf(&c, 1, fmt, ap2); + alen = vsnprintf(&c, 1, fmt, ap2); va_end(ap2); - if (len <= 0) { + if (alen <= 0) { /* Either the vsnprintf failed or the format resulted in * no characters being formatted. In the former case, we * ought to return NULL, in the latter we ought to return @@ -1252,60 +1312,51 @@ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) return s; } - s = talloc_realloc(NULL, s, char, s_len + len+1); + s = talloc_realloc(NULL, s, char, slen + alen + 1); if (!s) return NULL; va_copy(ap2, ap); - vsnprintf(s+s_len, len+1, fmt, ap2); + vsnprintf(s + slen, alen + 1, fmt, ap2); va_end(ap2); - _talloc_set_name_const(s, s); + _talloc_set_name_const(s, s); return s; } /** * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Good for gradually + * accumulating output into a string buffer. Appends at the end + * of the string. + **/ +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +{ + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap); +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, * and return @p s, which may have moved. Always appends at the * end of the talloc'ed buffer, not the end of the string. **/ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) { - struct talloc_chunk *tc; - int len, s_len; - va_list ap2; - char c; + size_t slen; - if (s == NULL) { + if (unlikely(!s)) { return talloc_vasprintf(NULL, fmt, ap); } - tc = talloc_chunk_from_ptr(s); - - s_len = tc->size - 1; - - va_copy(ap2, ap); - len = vsnprintf(&c, 1, fmt, ap2); - va_end(ap2); - - if (len <= 0) { - /* Either the vsnprintf failed or the format resulted in - * no characters being formatted. In the former case, we - * ought to return NULL, in the latter we ought to return - * the original string. Most current callers of this - * function expect it to never return NULL. - */ - return s; + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; } - s = talloc_realloc(NULL, s, char, s_len + len+1); - if (!s) return NULL; - - va_copy(ap2, ap); - vsnprintf(s+s_len, len+1, fmt, ap2); - va_end(ap2); - _talloc_set_name_const(s, s); - - return s; + return __talloc_vaslenprintf_append(s, slen, fmt, ap); } /* diff --git a/source3/lib/talloc/talloc.h b/source3/lib/talloc/talloc.h index 95152a1416..e103391681 100644 --- a/source3/lib/talloc/talloc.h +++ b/source3/lib/talloc/talloc.h @@ -111,6 +111,7 @@ typedef void TALLOC_CTX; #define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) #define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) #define talloc_destroy(ctx) talloc_free(ctx) +#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) #endif /* The following definitions come from talloc.c */ @@ -152,15 +153,6 @@ void talloc_enable_leak_report(void); void talloc_enable_leak_report_full(void); void *_talloc_zero(const void *ctx, size_t size, const char *name); void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); -char *talloc_strdup(const void *t, const char *p); -char *talloc_strndup(const void *t, const char *p, size_t n); -char *talloc_append_string(const void *t, char *orig, const char *append); -char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); @@ -171,4 +163,20 @@ void *talloc_find_parent_byname(const void *ctx, const char *name); void talloc_show_parents(const void *context, FILE *file); int talloc_is_parent(const void *context, const void *ptr); +char *talloc_strdup(const void *t, const char *p); +char *talloc_strdup_append(char *s, const char *a); +char *talloc_strdup_append_buffer(char *s, const char *a); + +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_strndup_append(char *s, const char *a, size_t n); +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); + +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + #endif diff --git a/source3/lib/talloc/testsuite.c b/source3/lib/talloc/testsuite.c index 2e3ae65082..e16c91f8b9 100644 --- a/source3/lib/talloc/testsuite.c +++ b/source3/lib/talloc/testsuite.c @@ -106,7 +106,7 @@ static bool test_ref1(void) { void *root, *p1, *p2, *ref, *r1; - printf("test: ref1 [\nSINGLE REFERENCE FREE\n]\n"); + printf("test: ref1\n# SINGLE REFERENCE FREE\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -162,7 +162,7 @@ static bool test_ref2(void) { void *root, *p1, *p2, *ref, *r1; - printf("test: ref2 [\nDOUBLE REFERENCE FREE\n]\n"); + printf("test: ref2\n# DOUBLE REFERENCE FREE\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); talloc_named_const(p1, 1, "x1"); @@ -217,7 +217,7 @@ static bool test_ref3(void) { void *root, *p1, *p2, *ref, *r1; - printf("test: ref3 [\nPARENT REFERENCE FREE\n]\n"); + printf("test: ref3\n# PARENT REFERENCE FREE\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -256,7 +256,7 @@ static bool test_ref4(void) { void *root, *p1, *p2, *ref, *r1; - printf("test: ref4 [\nREFERRER REFERENCE FREE\n]\n"); + printf("test: ref4\n# REFERRER REFERENCE FREE\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -306,7 +306,7 @@ static bool test_unlink1(void) { void *root, *p1, *p2, *ref, *r1; - printf("test: unlink [\nUNLINK\n]\n"); + printf("test: unlink\n# UNLINK\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -358,7 +358,7 @@ static bool test_misc(void) double *d; const char *name; - printf("test: misc [\nMISCELLANEOUS\n]\n"); + printf("test: misc\n# MISCELLANEOUS\n"); root = talloc_new(NULL); @@ -419,15 +419,15 @@ static bool test_misc(void) p2 = talloc_strndup(p1, "foo", 2); torture_assert("misc", strcmp("fo", p2) == 0, "strndup doesn't work\n"); - p2 = talloc_asprintf_append(p2, "o%c", 'd'); + p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd'); torture_assert("misc", strcmp("food", p2) == 0, - "talloc_asprintf_append doesn't work\n"); + "talloc_asprintf_append_buffer doesn't work\n"); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 3); - p2 = talloc_asprintf_append(NULL, "hello %s", "world"); + p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world"); torture_assert("misc", strcmp("hello world", p2) == 0, - "talloc_asprintf_append doesn't work\n"); + "talloc_asprintf_append_buffer doesn't work\n"); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 3); talloc_free(p2); @@ -509,7 +509,7 @@ static bool test_realloc(void) { void *root, *p1, *p2; - printf("test: realloc [\nREALLOC\n]\n"); + printf("test: realloc\n# REALLOC\n"); root = talloc_new(NULL); @@ -553,7 +553,7 @@ static bool test_realloc(void) talloc_free(root); - printf("success: REALLOC\n"); + printf("success: realloc\n"); return true; } @@ -617,7 +617,7 @@ static bool test_type(void) }; struct el1 *el1; - printf("test: type [\ntalloc type checking\n]\n"); + printf("test: type\n# talloc type checking\n"); root = talloc_new(NULL); @@ -646,7 +646,7 @@ static bool test_steal(void) { void *root, *p1, *p2; - printf("test: steal [\nSTEAL\n]\n"); + printf("test: steal\n# STEAL\n"); root = talloc_new(NULL); @@ -702,7 +702,7 @@ static bool test_move(void) int *x; } *t1, *t2; - printf("test: move [\nMOVE\n]\n"); + printf("test: move\n# MOVE\n"); root = talloc_new(NULL); @@ -732,7 +732,7 @@ static bool test_realloc_fn(void) { void *root, *p1; - printf("test: realloc_fn [\ntalloc_realloc_fn\n]\n"); + printf("test: realloc_fn\n# talloc_realloc_fn\n"); root = talloc_new(NULL); @@ -757,7 +757,7 @@ static bool test_unref_reparent(void) { void *root, *p1, *p2, *c1; - printf("test: unref_reparent [\nUNREFERENCE AFTER PARENT FREED\n]\n"); + printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "orig parent"); @@ -794,7 +794,7 @@ static bool test_speed(void) int i; struct timeval tv; - printf("test: speed [\nTALLOC VS MALLOC SPEED\n]\n"); + printf("test: speed\n# TALLOC VS MALLOC SPEED\n"); tv = timeval_current(); count = 0; @@ -840,7 +840,7 @@ static bool test_lifeless(void) char *parent, *child; void *child_owner = talloc_new(NULL); - printf("test: lifeless [\nTALLOC_UNLINK LOOP\n]\n"); + printf("test: lifeless\n# TALLOC_UNLINK LOOP\n"); parent = talloc_strdup(top, "parent"); child = talloc_strdup(parent, "child"); @@ -874,7 +874,7 @@ static bool test_loop(void) char *req2, *req3; } *req1; - printf("test: loop [\nTALLOC LOOP DESTRUCTION\n]\n"); + printf("test: loop\n# TALLOC LOOP DESTRUCTION\n"); parent = talloc_strdup(top, "parent"); req1 = talloc(parent, struct req1); @@ -908,7 +908,7 @@ static bool test_free_parent_deny_child(void) char *level2; char *level3; - printf("test: free_parent_deny_child [\nTALLOC FREE PARENT DENY CHILD\n]\n"); + printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n"); level1 = talloc_strdup(top, "level1"); level2 = talloc_strdup(level1, "level2"); @@ -938,7 +938,7 @@ static bool test_talloc_ptrtype(void) const char *location3; const char *location4; - printf("test: ptrtype [\nTALLOC PTRTYPE\n]\n"); + printf("test: ptrtype\n# TALLOC PTRTYPE\n"); s1 = talloc_ptrtype(top, s1);location1 = __location__; @@ -1024,7 +1024,7 @@ static bool test_talloc_free_in_destructor(void) void *level4; void **level5; - printf("test: free_in_destructor [\nTALLOC FREE IN DESTRUCTOR\n]\n"); + printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n"); level0 = talloc_new(NULL); level1 = talloc_new(level0); @@ -1053,7 +1053,7 @@ static bool test_autofree(void) #if _SAMBA_BUILD_ < 4 /* autofree test would kill smbtorture */ void *p; - printf("test: autofree [\nTALLOC AUTOFREE CONTEXT\n]\n"); + printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n"); p = talloc_autofree_context(); talloc_free(p); |