summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason King <jason.king@joyent.com>2018-09-16 01:10:39 +0000
committerJason King <jason.king@joyent.com>2019-06-26 20:34:18 +0000
commit454c1fdf661d38fd143da73a0ae9cf97ab5c2d6e (patch)
tree4c2e3a4e023129b6c7e320caadf446c1bff42247
parent356e1b4941ba70261404f9bb0255f70891042331 (diff)
downloadillumos-joyent-454c1fdf661d38fd143da73a0ae9cf97ab5c2d6e.tar.gz
OS-7858 Allow a range of bytes to be removed from a custrOS-7858
-rw-r--r--usr/src/lib/libcustr/common/custr.c75
-rw-r--r--usr/src/lib/libcustr/common/libcustr.h48
-rw-r--r--usr/src/lib/libcustr/common/mapfile-vers6
-rw-r--r--usr/src/test/util-tests/runfiles/default.run5
-rw-r--r--usr/src/test/util-tests/tests/Makefile2
-rw-r--r--usr/src/test/util-tests/tests/libcustr/Makefile50
-rw-r--r--usr/src/test/util-tests/tests/libcustr/custr_remove.c73
-rw-r--r--usr/src/test/util-tests/tests/libcustr/custr_trunc.c64
8 files changed, 319 insertions, 4 deletions
diff --git a/usr/src/lib/libcustr/common/custr.c b/usr/src/lib/libcustr/common/custr.c
index 6d3a003e6b..c321df5029 100644
--- a/usr/src/lib/libcustr/common/custr.c
+++ b/usr/src/lib/libcustr/common/custr.c
@@ -85,6 +85,81 @@ custr_reset(custr_t *cus)
cus->cus_data[0] = '\0';
}
+int
+custr_remove(custr_t *cus, size_t idx, size_t len)
+{
+ size_t endidx = idx + len;
+
+ /*
+ * Once gcc4 is dropped as a shadow compiler, we can migrate to
+ * using builtins for the overflow check.
+ */
+ if (endidx < idx || endidx < len) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (idx >= cus->cus_strlen || idx + len > cus->cus_strlen) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (len == 0)
+ return (0);
+
+ /* The +1 will include the terminating NUL in the move */
+ (void) memmove(cus->cus_data + idx, cus->cus_data + endidx,
+ cus->cus_strlen - endidx + 1);
+ cus->cus_strlen -= len;
+
+ /* The result should be NUL */
+ VERIFY0(cus->cus_data[cus->cus_strlen]);
+ return (0);
+}
+
+int
+custr_rremove(custr_t *cus, size_t ridx, size_t len)
+{
+ size_t idx;
+
+ if (ridx >= cus->cus_strlen) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ idx = cus->cus_strlen - ridx - 1;
+ return (custr_remove(cus, idx, len));
+}
+
+int
+custr_trunc(custr_t *cus, size_t idx)
+{
+ if (idx >= cus->cus_strlen) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ cus->cus_data[idx] = '\0';
+ cus->cus_strlen = idx;
+ return (0);
+}
+
+int
+custr_rtrunc(custr_t *cus, size_t ridx)
+{
+ size_t idx;
+
+ if (ridx >= cus->cus_strlen) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ idx = cus->cus_strlen - ridx - 1;
+ cus->cus_data[idx] = '\0';
+ cus->cus_strlen = idx;
+ return (0);
+}
+
size_t
custr_len(custr_t *cus)
{
diff --git a/usr/src/lib/libcustr/common/libcustr.h b/usr/src/lib/libcustr/common/libcustr.h
index 8fe5fee1b7..f8f15db07b 100644
--- a/usr/src/lib/libcustr/common/libcustr.h
+++ b/usr/src/lib/libcustr/common/libcustr.h
@@ -10,7 +10,7 @@
*/
/*
- * Copyright 2019, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
*/
#ifndef _LIBCUSTR_H
@@ -142,6 +142,52 @@ size_t custr_len(custr_t *);
void custr_reset(custr_t *);
/*
+ * custr_remove(cus, idx, len)
+ *
+ * Remove len bytes from cus, starting at idx.
+ *
+ * Returns 0 on success or -1 on failure. On failure, errno will be set to:
+ * EINVAL Either the idx or len parameter is invalid
+ *
+ */
+int custr_remove(custr_t *, size_t, size_t);
+
+/*
+ * custr_rremove(cus, idx, len)
+ *
+ * Remove len bytes from cus, starting at idx relative to the end of cus.
+ * That is, 0 = last byte of cus, 1 = second to last byte of cus, ...).
+ * The direction of removal is always towards the end of the string. I.e.
+ * 'custr_rremove(cus, 1, 2)' removes the last two bytes of cus.
+ *
+ * Returns 0 on success or -1 on failure. On failure, errno will be set to:
+ * EINVAL Either the idx or len parameter is invalid
+ *
+ */
+int custr_rremove(custr_t *, size_t, size_t);
+
+/*
+ * custr_trunc(cus, idx)
+ *
+ * Truncate cus starting at idx.
+ *
+ * Returns 0 on success or -1 on failure. On failure, errno is set to:
+ * EINVAL The idx value was invalid.
+ */
+int custr_trunc(custr_t *, size_t);
+
+/*
+ * custr_rtrunc(cus, idx)
+ *
+ * Truncate cus starting at idx relative to the end of cus (similar to how
+ * the idx paramter is treated with custr_rremove()).
+ *
+ * Returns 0 on success or -1 on failure. On failure, errno is set to:
+ * EINVAL The idx value was invalid.
+ */
+int custr_rtrunc(custr_t *, size_t);
+
+/*
* Retrieve a const pointer to a NUL-terminated string version of the contents
* of the dynamic string. Storage for this string should not be freed, and
* the pointer will be invalidated by any mutations to the dynamic string.
diff --git a/usr/src/lib/libcustr/common/mapfile-vers b/usr/src/lib/libcustr/common/mapfile-vers
index f94636b6f5..53b94164ad 100644
--- a/usr/src/lib/libcustr/common/mapfile-vers
+++ b/usr/src/lib/libcustr/common/mapfile-vers
@@ -10,7 +10,7 @@
#
#
-# Copyright 2019, Joyent, Inc.
+# Copyright 2019 Joyent, Inc.
#
#
@@ -42,7 +42,11 @@ SYMBOL_VERSION ILLUMOSprivate {
custr_cstr;
custr_free;
custr_len;
+ custr_remove;
custr_reset;
+ custr_rremove;
+ custr_rtrunc;
+ custr_trunc;
custr_xalloc;
custr_xalloc_buf;
local:
diff --git a/usr/src/test/util-tests/runfiles/default.run b/usr/src/test/util-tests/runfiles/default.run
index f8569b1423..c124a9c2ba 100644
--- a/usr/src/test/util-tests/runfiles/default.run
+++ b/usr/src/test/util-tests/runfiles/default.run
@@ -13,7 +13,7 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
-# Copyright 2019, Joyent, Inc.
+# Copyright 2019 Joyent, Inc.
#
[DEFAULT]
@@ -60,3 +60,6 @@ tests = ['afl-fast', 'gcc-libstdc++', 'llvm-stdcxxabi']
[/opt/util-tests/tests/ctf]
pre = precheck
tests = [ 'ctftest' ]
+
+[/opt/util-tests/tests/libcustr]
+tests = ['custr_remove', 'custr_trunc']
diff --git a/usr/src/test/util-tests/tests/Makefile b/usr/src/test/util-tests/tests/Makefile
index cb2d3028da..cb687ecdf6 100644
--- a/usr/src/test/util-tests/tests/Makefile
+++ b/usr/src/test/util-tests/tests/Makefile
@@ -19,6 +19,6 @@
SUBDIRS = date dis dladm iconv libnvpair_json libsff printf xargs grep_xpg4
SUBDIRS += demangle mergeq workq chown
-SUBDIRS += bunyan awk smbios libjedec ctf
+SUBDIRS += bunyan awk smbios libjedec ctf libcustr
include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/util-tests/tests/libcustr/Makefile b/usr/src/test/util-tests/tests/libcustr/Makefile
new file mode 100644
index 0000000000..3aa4c5c76a
--- /dev/null
+++ b/usr/src/test/util-tests/tests/libcustr/Makefile
@@ -0,0 +1,50 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Joyent, Inc.
+#
+
+include $(SRC)/Makefile.master
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests
+TESTDIR = $(ROOTOPTPKG)/tests/libcustr
+
+PROGS = custr_remove custr_trunc
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+CMDS = $(PROGS:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+LDLIBS += -lcustr
+
+all: $(PROGS)
+
+install: all $(CMDS) $(OUTFILES)
+
+clobber: clean
+ -$(RM) $(PROGS)
+
+clean:
+
+$(CMDS): $(TESTDIR) $(PROG)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %
+ $(INS.file)
+
+%: %.c
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
diff --git a/usr/src/test/util-tests/tests/libcustr/custr_remove.c b/usr/src/test/util-tests/tests/libcustr/custr_remove.c
new file mode 100644
index 0000000000..e58ab8c22a
--- /dev/null
+++ b/usr/src/test/util-tests/tests/libcustr/custr_remove.c
@@ -0,0 +1,73 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Joyent, Inc.
+ */
+
+#include <errno.h>
+#include <libcustr.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/debug.h>
+
+static void
+expect(const char *var, custr_t *cu, const char *str, const char *file,
+ size_t line)
+{
+ if (strcmp(custr_cstr(cu), str) == 0)
+ return;
+
+ char msgbuf[256];
+
+ (void) snprintf(msgbuf, sizeof (msgbuf), "%s == '%s' ('%s' == '%s')",
+ var, str, custr_cstr(cu), str);
+
+ assfail(msgbuf, file, line);
+}
+
+#define EXPECT(_cu, _str) expect(#_cu, _cu, _str, __FILE__, __LINE__)
+#define FAIL(_expr, _ev) \
+ VERIFY3S(_expr, ==, -1); \
+ VERIFY3S(errno, ==, (_ev))
+
+int
+main(void)
+{
+ custr_t *cu;
+
+ VERIFY0(custr_alloc(&cu));
+
+ VERIFY0(custr_append(cu, "12345"));
+ EXPECT(cu, "12345");
+
+ FAIL(custr_remove(cu, 6, 2), EINVAL);
+ FAIL(custr_remove(cu, 2, 10), EINVAL);
+ FAIL(custr_rremove(cu, 6, 2), EINVAL);
+ FAIL(custr_rremove(cu, 2, 10), EINVAL);
+
+ VERIFY0(custr_remove(cu, 0, 1));
+ EXPECT(cu, "2345");
+ VERIFY0(custr_rremove(cu, 1, 2));
+ EXPECT(cu, "23");
+
+ VERIFY0(custr_append(cu, "456"));
+ EXPECT(cu, "23456");
+
+ VERIFY0(custr_remove(cu, 1, 2));
+ EXPECT(cu, "256");
+
+ VERIFY0(custr_rremove(cu, 1, 2));
+ EXPECT(cu, "2");
+
+ return (0);
+}
diff --git a/usr/src/test/util-tests/tests/libcustr/custr_trunc.c b/usr/src/test/util-tests/tests/libcustr/custr_trunc.c
new file mode 100644
index 0000000000..6825512ad9
--- /dev/null
+++ b/usr/src/test/util-tests/tests/libcustr/custr_trunc.c
@@ -0,0 +1,64 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Joyent, Inc.
+ */
+
+#include <errno.h>
+#include <libcustr.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/debug.h>
+
+static void
+expect(const char *var, custr_t *cu, const char *str, const char *file,
+ size_t line)
+{
+ if (strcmp(custr_cstr(cu), str) == 0)
+ return;
+
+ char msgbuf[256];
+
+ (void) snprintf(msgbuf, sizeof (msgbuf), "%s == '%s' ('%s' == '%s')",
+ var, str, custr_cstr(cu), str);
+
+ assfail(msgbuf, file, line);
+}
+
+#define EXPECT(_cu, _str) expect(#_cu, _cu, _str, __FILE__, __LINE__)
+#define FAIL(_expr, _ev) \
+ VERIFY3S(_expr, ==, -1); \
+ VERIFY3S(errno, ==, (_ev))
+
+int
+main(void)
+{
+ custr_t *cu;
+
+ VERIFY0(custr_alloc(&cu));
+
+ VERIFY0(custr_append(cu, "12345"));
+ EXPECT(cu, "12345");
+
+ FAIL(custr_trunc(cu, 6), EINVAL);
+ FAIL(custr_rtrunc(cu, 10), EINVAL);
+
+ VERIFY0(custr_trunc(cu, 3));
+ EXPECT(cu, "123");
+
+ VERIFY0(custr_rtrunc(cu, 1));
+ EXPECT(cu, "1");
+
+ return (0);
+}