summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/libreboot-utils/include/common.h2
-rw-r--r--util/libreboot-utils/lib/string.c51
2 files changed, 53 insertions, 0 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h
index ebad01bf..dac87fac 100644
--- a/util/libreboot-utils/include/common.h
+++ b/util/libreboot-utils/include/common.h
@@ -375,6 +375,8 @@ int scmp(const char *a, const char *b,
size_t maxlen, int *rval);
int sdup(const char *s,
size_t n, char **dest);
+int scatn(ssize_t sc, const char **sv,
+ size_t max, char **rval);
int scat(const char *s1, const char *s2,
size_t n, char **dest);
int dcat(const char *s, size_t n,
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c
index 0329c6c3..b639f0a4 100644
--- a/util/libreboot-utils/lib/string.c
+++ b/util/libreboot-utils/lib/string.c
@@ -117,6 +117,57 @@ sdup(const char *s,
return 0;
}
+/* concatenate N number of strings */
+/* slen already checks null/termination */
+int
+scatn(ssize_t sc, const char **sv,
+ size_t max, char **rval)
+{
+ ssize_t i = 0;
+
+ size_t ts = 0;
+ size_t *size = NULL;
+
+ char *ct = NULL;
+ int saved_errno = errno;
+
+ if (if_err(sc <= 0, EINVAL) ||
+ if_err(sc > SIZE_MAX / sizeof(size_t), EOVERFLOW) ||
+ if_err(sv == NULL, EINVAL) ||
+ if_err((size = malloc(sizeof(size_t) * sc)) == NULL, ENOMEM))
+ goto err;
+
+ for (i = 0; i < sc; i++, ts += size[i])
+ if (if_err(sv[i] == NULL, EINVAL) ||
+ slen(sv[i], max, &size[i]) < 0 ||
+ if_err(size[i] > max - 1, EOVERFLOW) ||
+ if_err((size[i] + ts) < ts, EOVERFLOW))
+ goto err;
+
+ if (if_err(ts > SIZE_MAX - 1, EOVERFLOW) ||
+ if_err(ts > max - 1, EOVERFLOW) ||
+ if_err((ct = malloc(ts + 1)) == NULL, ENOMEM))
+ goto err;
+
+ for (ts = i = 0; i < sc; i++, ts += size[i])
+ memcpy(ct + ts, sv[i], size[i]);
+
+ *(ct + ts) = '\0';
+ *rval = ct;
+
+ errno = saved_errno;
+ return 0;
+err:
+ if (ct != NULL)
+ free(ct);
+ if (size != NULL)
+ free(size);
+ if (errno == saved_errno)
+ errno = EFAULT;
+
+ return -1;
+}
+
/* strict strcat */
int
scat(const char *s1, const char *s2,