*** /dev/null Tue Mar 11 06:05:13 2025
--- - Tue Mar 11 06:05:27 2025
***************
*** 0 ****
--- 1,219 ----
+ /*
+ ** OSSP path - Filesystem Path Manipulation
+ ** Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
+ ** Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
+ ** Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
+ **
+ ** This file is part of OSSP path, a filesystem path manipulation library
+ ** which can be found at http://www.ossp.org/pkg/lib/path/.
+ **
+ ** Permission to use, copy, modify, and distribute this software for
+ ** any purpose with or without fee is hereby granted, provided that
+ ** the above copyright notice and this permission notice appear in all
+ ** copies.
+ **
+ ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+ ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ ** SUCH DAMAGE.
+ **
+ ** path_util.c: utility functions
+ */
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <string.h>
+
+ #include "path.h"
+ #include "path_util.h"
+
+ /* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */
+ int path_mvxprintf(int (*output)(void *ctx, const char *buffer, size_t bufsize), void *ctx, const char *format, va_list ap)
+ {
+ /* sufficient integer buffer: <available-bits> x log_10(2) + safety */
+ char ibuf[((sizeof(int)*8)/3)+10];
+ char libuf[((sizeof(long)*8)/3)+10];
+ char *cp;
+ char c;
+ int d;
+ long ld;
+ int n;
+ int bytes;
+ int islong;
+
+ if (format == NULL || ap == NULL)
+ return -1;
+ bytes = 0;
+ while (*format != '\0') {
+ if (*format == '%') {
+ c = *(format+1);
+ islong = 0;
+ if (c == 'l') {
+ islong = 1;
+ format++;
+ c = *(format+1);
+ }
+ if (c == '%') {
+ /* expand "%%" */
+ cp = &c;
+ n = sizeof(char);
+ }
+ else if (c == 'c') {
+ /* expand "%c" */
+ c = (char)va_arg(ap, int);
+ cp = &c;
+ n = sizeof(char);
+ }
+ else if (c == 's') {
+ /* expand "%s" */
+ if ((cp = (char *)va_arg(ap, char *)) == NULL)
+ cp = "(null)";
+ n = strlen(cp);
+ }
+ else if (c == 'd') {
+ /* expand "%d" */
+ if (islong) {
+ ld = (long)va_arg(ap, long);
+ #ifdef HAVE_SNPRINTF
+ snprintf(libuf, sizeof(libuf), "%ld", ld); /* explicitly secure */
+ #else
+ sprintf(libuf, "%ld", ld); /* implicitly secure */
+ #endif
+ cp = libuf;
+ }
+ else {
+ d = (int)va_arg(ap, int);
+ #ifdef HAVE_SNPRINTF
+ snprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
+ #else
+ sprintf(ibuf, "%d", d); /* implicitly secure */
+ #endif
+ cp = ibuf;
+ }
+ n = strlen(cp);
+ }
+ else {
+ /* any other "%X" */
+ cp = (char *)format;
+ n = 2;
+ }
+ format += 2;
+ }
+ else {
+ /* plain text */
+ cp = (char *)format;
+ if ((format = strchr(cp, '%')) == NULL)
+ format = strchr(cp, '\0');
+ n = format - cp;
+ }
+ /* perform output operation */
+ if (output != NULL)
+ if ((n = output(ctx, cp, n)) == -1)
+ break;
+ bytes += n;
+ }
+ return bytes;
+ }
+
+ /* output callback function context for path_mvsnprintf() */
+ typedef struct {
+ char *bufptr;
+ size_t buflen;
+ } path_mvsnprintf_cb_t;
+
+ /* output callback function for path_mvsnprintf() */
+ static int path_mvsnprintf_cb(void *_ctx, const char *buffer, size_t bufsize)
+ {
+ path_mvsnprintf_cb_t *ctx = (path_mvsnprintf_cb_t *)_ctx;
+
+ if (bufsize > ctx->buflen)
+ return -1;
+ memcpy(ctx->bufptr, buffer, bufsize);
+ ctx->bufptr += bufsize;
+ ctx->buflen -= bufsize;
+ return bufsize;
+ }
+
+ /* minimal vsnprintf(3) variant which supports %{c,s,d} only */
+ int path_mvsnprintf(char *buffer, size_t bufsize, const char *format, va_list ap)
+ {
+ int n;
+ path_mvsnprintf_cb_t ctx;
+
+ if (format == NULL || ap == NULL)
+ return -1;
+ if (buffer != NULL && bufsize == 0)
+ return -1;
+ if (buffer == NULL)
+ /* just determine output length */
+ n = path_mvxprintf(NULL, NULL, format, ap);
+ else {
+ /* perform real output */
+ ctx.bufptr = buffer;
+ ctx.buflen = bufsize;
+ n = path_mvxprintf(path_mvsnprintf_cb, &ctx, format, ap);
+ if (n != -1 && ctx.buflen == 0)
+ n = -1;
+ if (n != -1)
+ *(ctx.bufptr) = '\0';
+ }
+ return n;
+ }
+
+ /* minimal snprintf(3) variant which supports %{c,s,d} only */
+ int path_msnprintf(char *buffer, size_t bufsize, const char *format, ...)
+ {
+ int chars;
+ va_list ap;
+
+ /* pass through to va_list based variant */
+ va_start(ap, format);
+ chars = path_mvsnprintf(buffer, bufsize, format, ap);
+ va_end(ap);
+
+ return chars;
+ }
+
+ /* minimal vasnprintf(3) variant which supports %{c,s,d} only */
+ char *path_mvasnprintf(const char *format, va_list ap)
+ {
+ char *buffer;
+ size_t bufsize;
+ va_list apbak;
+
+ apbak = ap;
+ if ((bufsize = path_mvsnprintf(NULL, -1, format, ap)) == -1)
+ return NULL;
+ if ((buffer = malloc(bufsize+1)) == NULL)
+ return NULL;
+ ap = apbak;
+ if ((bufsize = path_mvsnprintf(buffer, bufsize, format, ap)) == -1) {
+ free(buffer);
+ return NULL;
+ }
+ return buffer;
+ }
+
+ /* minimal asnprintf(3) variant which supports %{c,s,d} only */
+ char *path_masnprintf(const char *format, ...)
+ {
+ char *buffer;
+ va_list ap;
+
+ /* pass through to va_list based variant */
+ va_start(ap, format);
+ buffer = path_mvasnprintf(format, ap);
+ va_end(ap);
+
+ return buffer;
+ }
+
|