summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcmdutils/common/custr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libcmdutils/common/custr.c')
-rw-r--r--usr/src/lib/libcmdutils/common/custr.c87
1 files changed, 71 insertions, 16 deletions
diff --git a/usr/src/lib/libcmdutils/common/custr.c b/usr/src/lib/libcmdutils/common/custr.c
index 1ec72de9dd..03a9561934 100644
--- a/usr/src/lib/libcmdutils/common/custr.c
+++ b/usr/src/lib/libcmdutils/common/custr.c
@@ -20,13 +20,20 @@
#include <stdlib.h>
#include <err.h>
#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
#include "libcmdutils.h"
+typedef enum {
+ CUSTR_FIXEDBUF = 0x01
+} custr_flags_t;
+
struct custr {
size_t cus_strlen;
size_t cus_datalen;
char *cus_data;
+ custr_flags_t cus_flags;
};
#define STRING_CHUNK_SIZE 64
@@ -53,23 +60,15 @@ custr_cstr(custr_t *cus)
return (cus->cus_data);
}
-int
-custr_appendc(custr_t *cus, char newc)
-{
- char news[2];
-
- news[0] = newc;
- news[1] = '\0';
-
- return (custr_append(cus, news));
-}
-
-int
-custr_append(custr_t *cus, const char *news)
+static int
+custr_append_vprintf(custr_t *cus, const char *fmt, va_list ap)
{
- size_t len = strlen(news);
+ int len = vsnprintf(NULL, 0, fmt, ap);
size_t chunksz = STRING_CHUNK_SIZE;
+ if (len == -1)
+ return (len);
+
while (chunksz < len) {
chunksz *= 2;
}
@@ -78,6 +77,11 @@ custr_append(custr_t *cus, const char *news)
char *new_data;
size_t new_datalen = cus->cus_datalen + chunksz;
+ if (cus->cus_flags & CUSTR_FIXEDBUF) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+
/*
* Allocate replacement memory:
*/
@@ -104,13 +108,41 @@ custr_append(custr_t *cus, const char *news)
/*
* Append new string to existing string:
*/
- (void) memcpy(cus->cus_data + cus->cus_strlen, news, len + 1);
+ len = vsnprintf(cus->cus_data + cus->cus_strlen,
+ (uintptr_t)cus->cus_data - (uintptr_t)cus->cus_strlen, fmt, ap);
+ if (len == -1)
+ return (len);
cus->cus_strlen += len;
return (0);
}
int
+custr_appendc(custr_t *cus, char newc)
+{
+ return (custr_append_printf(cus, "%c", newc));
+}
+
+int
+custr_append_printf(custr_t *cus, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = custr_append_vprintf(cus, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
+
+int
+custr_append(custr_t *cus, const char *name)
+{
+ return (custr_append_printf(cus, "%s", name));
+}
+
+int
custr_alloc(custr_t **cus)
{
custr_t *t;
@@ -124,12 +156,35 @@ custr_alloc(custr_t **cus)
return (0);
}
+int
+custr_alloc_buf(custr_t **cus, void *buf, size_t buflen)
+{
+ int ret;
+
+ if (buflen == 0 || buf == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((ret = custr_alloc(cus)) != 0)
+ return (ret);
+
+ (*cus)->cus_data = buf;
+ (*cus)->cus_datalen = buflen;
+ (*cus)->cus_strlen = 0;
+ (*cus)->cus_flags = CUSTR_FIXEDBUF;
+ (*cus)->cus_data[0] = '\0';
+
+ return (0);
+}
+
void
custr_free(custr_t *cus)
{
if (cus == NULL)
return;
- free(cus->cus_data);
+ if ((cus->cus_flags & CUSTR_FIXEDBUF) == 0)
+ free(cus->cus_data);
free(cus);
}