diff options
| author | Greg Hudson <ghudson@mit.edu> | 2008-10-28 22:03:35 +0000 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2008-10-28 22:03:35 +0000 |
| commit | 88cd11e1087decfebf0fd87e5243dab9efc9c686 (patch) | |
| tree | ce245e9c6298934b486d3cfa92557304639efaa6 /src/util/support/k5buf.c | |
| parent | 886967fbb7889a6a2654b5256bb9bb442382ccde (diff) | |
| download | krb5-88cd11e1087decfebf0fd87e5243dab9efc9c686.tar.gz krb5-88cd11e1087decfebf0fd87e5243dab9efc9c686.tar.xz krb5-88cd11e1087decfebf0fd87e5243dab9efc9c686.zip | |
In the k5buf module, add a function to append formatted data to a
buffer.
ticket: 6200
status: open
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20932 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util/support/k5buf.c')
| -rw-r--r-- | src/util/support/k5buf.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/util/support/k5buf.c b/src/util/support/k5buf.c index 747490280..23fb20365 100644 --- a/src/util/support/k5buf.c +++ b/src/util/support/k5buf.c @@ -115,6 +115,71 @@ void krb5int_buf_add_len(struct k5buf *buf, const char *data, size_t len) buf->data[buf->len] = '\0'; } +void krb5int_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) +{ + va_list ap; + int r; + size_t remaining; + char *tmp; + + if (buf->buftype == ERROR) + return; + remaining = buf->space - buf->len; + + if (buf->buftype == FIXED) { + /* Format the data directly into the fixed buffer. */ + va_start(ap, fmt); + r = vsnprintf(buf->data + buf->len, remaining, fmt, ap); + va_end(ap); + if (SNPRINTF_OVERFLOW(r, remaining)) + buf->buftype = ERROR; + else + buf->len += (unsigned int) r; + return; + } + + /* Optimistically format the data directly into the dynamic buffer. */ + assert(buf->buftype == DYNAMIC); + va_start(ap, fmt); + r = vsnprintf(buf->data + buf->len, remaining, fmt, ap); + va_end(ap); + if (!SNPRINTF_OVERFLOW(r, remaining)) { + buf->len += (unsigned int) r; + return; + } + + if (r >= 0) { + /* snprintf correctly told us how much space is required. */ + if (!ensure_space(buf, r)) + return; + remaining = buf->space - buf->len; + va_start(ap, fmt); + r = vsnprintf(buf->data + buf->len, remaining, fmt, ap); + va_end(ap); + if (SNPRINTF_OVERFLOW(r, remaining)) /* Shouldn't ever happen. */ + buf->buftype = ERROR; + else + buf->len += (unsigned int) r; + return; + } + + /* It's a pre-C99 snprintf implementation, or something else went + wrong. Fall back to asprintf. */ + va_start(ap, fmt); + r = vasprintf(&tmp, fmt, ap); + va_end(ap); + if (r < 0) { + buf->buftype = ERROR; + return; + } + if (ensure_space(buf, r)) { + /* Copy the temporary string into buf, including terminator. */ + memcpy(buf->data + buf->len, tmp, r + 1); + buf->len += r; + } + free(tmp); +} + void krb5int_buf_truncate(struct k5buf *buf, size_t len) { if (buf->buftype == ERROR) |
