196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow/*
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * This file and its contents are supplied under the terms of the
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * Common Development and Distribution License ("CDDL"), version 1.0.
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * You may only use this file in accordance with the terms of version
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * 1.0 of the CDDL.
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow *
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * A full copy of the text of the CDDL should have accompanied this
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * source. A copy of the CDDL is also available via the Internet at
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * http://www.illumos.org/license/CDDL.
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow/*
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * String utility functions with dynamic memory management.
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow/*
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * Copyright 2016 Joyent, Inc.
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow#include <stdlib.h>
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow#include <err.h>
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow#include <string.h>
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi#include <stdio.h>
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi#include <stdarg.h>
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi#include <sys/debug.h>
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow#include "libcmdutils.h"
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchitypedef enum {
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi CUSTR_FIXEDBUF = 0x01
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi} custr_flags_t;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowstruct custr {
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow size_t cus_strlen;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow size_t cus_datalen;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow char *cus_data;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi custr_flags_t cus_flags;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow};
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow#define STRING_CHUNK_SIZE 64
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowvoid
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowcustr_reset(custr_t *cus)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow{
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow if (cus->cus_data == NULL)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow cus->cus_strlen = 0;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow cus->cus_data[0] = '\0';
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow}
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowsize_t
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowcustr_len(custr_t *cus)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow{
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return (cus->cus_strlen);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow}
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowconst char *
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowcustr_cstr(custr_t *cus)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow{
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (cus->cus_data == NULL) {
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi VERIFY(cus->cus_strlen == 0);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi VERIFY(cus->cus_datalen == 0);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi /*
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * This function should never return NULL. If no buffer has
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * been allocated, return a pointer to a zero-length string.
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi */
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return ("");
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi }
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (cus->cus_data);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow}
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowint
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchicustr_append_vprintf(custr_t *cus, const char *fmt, va_list ap)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow{
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi int len = vsnprintf(NULL, 0, fmt, ap);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow size_t chunksz = STRING_CHUNK_SIZE;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (len == -1)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (len);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow while (chunksz < len) {
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow chunksz *= 2;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow }
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow if (len + cus->cus_strlen + 1 >= cus->cus_datalen) {
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow char *new_data;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow size_t new_datalen = cus->cus_datalen + chunksz;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (cus->cus_flags & CUSTR_FIXEDBUF) {
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi errno = EOVERFLOW;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (-1);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi }
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow /*
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * Allocate replacement memory:
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow if ((new_data = malloc(new_datalen)) == NULL) {
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return (-1);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow }
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow /*
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * Copy existing data into replacement memory and free
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * the old memory.
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow if (cus->cus_data != NULL) {
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow (void) memcpy(new_data, cus->cus_data,
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow cus->cus_strlen + 1);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow free(cus->cus_data);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow }
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow /*
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * Swap in the replacement buffer:
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow cus->cus_data = new_data;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow cus->cus_datalen = new_datalen;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow }
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow /*
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow * Append new string to existing string:
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow */
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi len = vsnprintf(cus->cus_data + cus->cus_strlen,
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi (uintptr_t)cus->cus_data - (uintptr_t)cus->cus_strlen, fmt, ap);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (len == -1)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (len);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow cus->cus_strlen += len;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return (0);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow}
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchiint
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchicustr_appendc(custr_t *cus, char newc)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi{
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (custr_append_printf(cus, "%c", newc));
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi}
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchiint
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchicustr_append_printf(custr_t *cus, const char *fmt, ...)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi{
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi va_list ap;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi int ret;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi va_start(ap, fmt);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi ret = custr_append_vprintf(cus, fmt, ap);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi va_end(ap);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (ret);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi}
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchiint
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchicustr_append(custr_t *cus, const char *name)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi{
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (custr_append_printf(cus, "%s", name));
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi}
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowint
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowcustr_alloc(custr_t **cus)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow{
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow custr_t *t;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow if ((t = calloc(1, sizeof (*t))) == NULL) {
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow *cus = NULL;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return (-1);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow }
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow *cus = t;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return (0);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow}
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchiint
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchicustr_alloc_buf(custr_t **cus, void *buf, size_t buflen)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi{
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi int ret;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (buflen == 0 || buf == NULL) {
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi errno = EINVAL;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (-1);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi }
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if ((ret = custr_alloc(cus)) != 0)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (ret);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi (*cus)->cus_data = buf;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi (*cus)->cus_datalen = buflen;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi (*cus)->cus_strlen = 0;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi (*cus)->cus_flags = CUSTR_FIXEDBUF;
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi (*cus)->cus_data[0] = '\0';
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi return (0);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi}
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowvoid
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulowcustr_free(custr_t *cus)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow{
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow if (cus == NULL)
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow return;
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if ((cus->cus_flags & CUSTR_FIXEDBUF) == 0)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi free(cus->cus_data);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow free(cus);
196c7f05d2deba7404e90ad67f3861185c78ca2dJoshua M. Clulow}