Index: ossp-pkg/path/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/path/Makefile.in,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/path/Makefile.in,v' 2>/dev/null --- Makefile.in 2002/08/03 10:23:41 1.2 +++ Makefile.in 2002/08/03 21:00:14 1.3 @@ -50,7 +50,8 @@ TRUE = true LIB_NAME = libpath.la -LIB_OBJS = path_abs2rel.lo path_rel2abs.lo path_resolve.lo path_dirname.lo path_basename.lo +LIB_OBJS = path_abs2rel.lo path_rel2abs.lo path_resolve.lo \ + path_dirname.lo path_basename.lo path_temp.lo path_util.lo TST_NAME = path_test TST_OBJS = path_test.o Index: ossp-pkg/path/TODO RCS File: /v/ossp/cvs/ossp-pkg/path/TODO,v co -q -kk -p'1.2' '/v/ossp/cvs/ossp-pkg/path/TODO,v' | diff -u /dev/null - -L'ossp-pkg/path/TODO' 2>/dev/null --- ossp-pkg/path/TODO +++ - 2024-05-10 13:52:17.781373662 +0200 @@ -0,0 +1,12 @@ + +- restliche API auf path_rc_t umbauen +- add glob(*) from shpat +- add fnmatch(*) from shpat +- add tilde() from shpath/bres or bash-2.05a +- merge with shpat und proc/getcwd +- MAXPATHLEN should be PATH_MAXPATHLEN und + per AUtoconf herausgegfunden weredse +- path_test.pl in C umschreiben und in path_test.c einbauen +- path_test.c um path_resolve() checks erweitern +- path.pod per pod2man convertieren + Index: ossp-pkg/path/path.h RCS File: /v/ossp/cvs/ossp-pkg/path/path.h,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/path/path.h,v' 2>/dev/null --- path.h 2002/08/03 10:23:41 1.2 +++ path.h 2002/08/03 21:00:14 1.3 @@ -31,11 +31,26 @@ #ifndef __PATH_H__ #define __PATH_H__ +typedef enum { + PATH_OK = 0, + PATH_ERR_ARG, + PATH_ERR_USE, + PATH_ERR_INT, + PATH_ERR_SYS, + PATH_ERR_EXS +} path_rc_t; + +typedef enum { + PATH_TEMP_FILE, + PATH_TEMP_DIR +} path_temp_t; + char *path_abs2rel (char *, size_t, const char *, const char *); char *path_rel2abs (char *, size_t, const char *, const char *); char *path_resolve (char *, size_t, const char *); char *path_dirname (char *, size_t, const char *); char *path_basename (char *, size_t, const char *); +path_rc_t path_temp(path_temp_t id, const char *tmpl, char **res_ptr, size_t *res_size, int *res_fd); #endif /* __PATH_H__ */ Index: ossp-pkg/path/path.pod RCS File: /v/ossp/cvs/ossp-pkg/path/path.pod,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/path/path.pod,v' 2>/dev/null --- path.pod 2002/08/03 10:23:41 1.2 +++ path.pod 2002/08/03 21:00:15 1.3 @@ -32,7 +32,7 @@ =head1 NAME -B - Filesystem Path Manipulation +B - Filesystem Path Manipulation =head1 SYNOPSIS @@ -50,10 +50,14 @@ =head1 DESCRIPTION -B is a filesystem path conversion library. It allows one to -convert between absolute and relative paths and to resolve symlinks in a -path. The following Application Programming Interface (API) is provided -for this: +B is a filesystem path manipulation library. It allows one +to convert between absolute and relative paths and to resolve symbolic +links in a path. + +=head1 APPLICATION PROGRAMMING INTERFACE (API) + +The following Application Programming Interface (API) is provided by +B: =over 4 @@ -106,22 +110,24 @@ =item char *B(char *I, const size_t I, const char *I); -This function extracts the directory filename part from I and stores it -into the caller supplied buffer at I, but never more than I -bytes are written. The function returns a pointer to I on success, -and C on error. +This function extracts the directory filename part from I and +stores it into the caller supplied buffer at I, but never more +than I bytes are written. The function returns a pointer to +I on success, and C on error. =item char *B(char *I, const size_t I, const char *I); -This function extracts the base filename part from I and stores it into -the caller supplied buffer at I, but never more than I bytes -are written. The function returns a pointer to I on success, and -C on error. +This function extracts the base filename part from I and stores +it into the caller supplied buffer at I, but never more than +I bytes are written. The function returns a pointer to +I on success, and C on error. =back =head1 EXAMPLE +The code + char result[MAXPATHLEN]; char *path = path_abs2rel(result, sizeof(result), "/usr/src/sys", "/usr/local/lib"); @@ -179,8 +185,8 @@ path == "../../../sys/kern" /* It's correct but ... */ -That is correct, but a little redundant. If you wish get the simple an- -swer 'C', do the following. +That is correct, but a little redundant. If you wish get the simple +answer 'C', do the following. path = path_abs2rel(r0, sizeof(r0), path_resolve(r1, sizeof(r1), "/sys/kern"), @@ -194,12 +200,13 @@ =head1 AUTHORS -The path_abs2rel() and path_rel2abs() function was originally written in -December 1997 by I for his I project. The -path_resolve() function is derived from FreeBSD's realpath(3) function -which was written in February 1994 by I. The work off -of this code and the B library as a whole was written in January -2000 by I. +The path_abs2rel(3) and path_rel2abs(3) function was originally written +in December 1997 by I for his I project. +The path_resolve(3) function is derived from FreeBSD's realpath(3) +function which was written in February 1994 by I. +The work off of this code and the B library as a whole was +written in January 2000 by I for use in the B +project. =cut Index: ossp-pkg/path/path_temp.c RCS File: /v/ossp/cvs/ossp-pkg/path/path_temp.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/path/path_temp.c,v' | diff -u /dev/null - -L'ossp-pkg/path/path_temp.c' 2>/dev/null --- ossp-pkg/path/path_temp.c +++ - 2024-05-10 13:52:17.803642578 +0200 @@ -0,0 +1,195 @@ +/* +** OSSP path - Filesystem Path Manipulation +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** +** 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_temp.c: temporary pathname creation +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "path.h" +#include "path_util.h" + +static const char +path_temp_padchar[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +path_rc_t +path_temp( + path_temp_t id, + const char *tmpl, + char **res_ptr, + size_t *res_size, + int *res_fd) +{ + char tmpl_def[MAXPATHLEN]; + char path[MAXPATHLEN]; + char *tmpdir; + size_t n; + char *user; + char user_buf[4+((sizeof(long)*8)/3)+10]; + const char *cp; + const char *cpT; + char *cpP; + struct passwd *pw; + struct timeval tp; + struct timezone tzp; + pid_t pid; + pid_t ppid; + uid_t uid; + int r; + path_rc_t rc; + int fd; + + /* argument sanity checks */ + if (res_ptr == NULL && res_fd == NULL) + return PATH_ERR_ARG; + if (id == PATH_TEMP_DIR && res_fd != NULL) + return PATH_ERR_USE; + + /* determine temporary directory */ + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = getenv("TEMPDIR"); + if (tmpdir == NULL || tmpdir[0] == '\0') + tmpdir = "/tmp"; + + /* provide a reasonable fallback template */ + uid = getuid(); + if (tmpl == NULL || tmpl[0] == '\0') { + /* none or empty template */ + if ((pw = getpwuid(uid)) != NULL) + user = pw->pw_name; + else { + path_msnprintf(user_buf, sizeof(user_buf), "uid-%ld", (long)uid); + user = user_buf; + } + n = strlen(tmpdir); + path_msnprintf(tmpl_def, sizeof(tmpl_def), "%s%s%s.XXXXXXXX", + tmpdir, (tmpdir[n-1] != '/' ? "/" : ""), user_buf); + tmpl = tmpl_def; + } + else if (tmpl[0] != '/') { + /* non-absolute path template */ + n = strlen(tmpdir); + path_msnprintf(tmpl_def, sizeof(tmpl_def), "%s%s%s", + tmpdir, (tmpdir[n-1] != '/' ? "/" : ""), tmpl); + if (strchr(tmpl_def, 'X') == NULL) { + n = strlen(tmpl_def); + path_msnprintf(tmpl_def+n, sizeof(tmpl_def)-n, ".XXXXXXXX"); + } + tmpl = tmpl_def; + } + + /* seed PRNG as good as possible with POSIX features */ + gettimeofday(&tp, &tzp); + pid = getpid(); + ppid = getppid(); + srand( (unsigned int)tp.tv_sec + + (unsigned int)tp.tv_usec + + (unsigned int)uid + + (unsigned int)pid + + (unsigned int)ppid); + + /* create initial path */ + n = 0; + for (cpT = tmpl, cpP = path; *cpT != '\0'; cpT++, cpP++) { + if (*cpT == 'X') { + r = rand() % (sizeof(path_temp_padchar)-1); + *cpP = path_temp_padchar[r]; + n++; + } + else + *cpP = *cpT; + } + *cpP = '\0'; + if (n < 2) + return PATH_ERR_ARG; + + /* try to find a good temporary path */ + rc = PATH_ERR_INT; + fd = -1; + for (;;) { + /* try to create path */ + if (id == PATH_TEMP_FILE) { + if ((fd = open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) { + rc = PATH_OK; + break; + } + if (errno != EEXIST) + return PATH_ERR_SYS; + } + else if (id == PATH_TEMP_DIR) { + if (mkdir(path, 0700) == 0) { + rc = PATH_OK; + break; + } + if (errno != EEXIST) + return PATH_ERR_SYS; + } + else + return PATH_ERR_ARG; + + /* path collision found, so cycle through namespace */ + for (cpT = tmpl, cpP = path; *cpT != '\0'; cpT++, cpP++) { + if (*cpT == 'X') { + cp = strchr(path_temp_padchar, *cpP); + if (cp == NULL || *++cp == '\0') + *cpP = path_temp_padchar[0]; + else { + *cpP = *cp; + break; + } + } + } + if (*cpT == '\0') + return PATH_ERR_EXS; + } + + /* provide results */ + if (rc == PATH_OK) { + if (res_ptr != NULL) + *res_ptr = strdup(path); + else + unlink(path); + if (res_fd != NULL) + *res_fd = fd; + else + close(fd); + } + + return rc; +} + Index: ossp-pkg/path/path_util.c RCS File: /v/ossp/cvs/ossp-pkg/path/path_util.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/path/path_util.c,v' | diff -u /dev/null - -L'ossp-pkg/path/path_util.c' 2>/dev/null --- ossp-pkg/path/path_util.c +++ - 2024-05-10 13:52:17.806272296 +0200 @@ -0,0 +1,219 @@ +/* +** OSSP path - Filesystem Path Manipulation +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** +** 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 +#include +#include +#include + +#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: 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; +} + Index: ossp-pkg/path/path_util.h RCS File: /v/ossp/cvs/ossp-pkg/path/path_util.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/path/path_util.h,v' | diff -u /dev/null - -L'ossp-pkg/path/path_util.h' 2>/dev/null --- ossp-pkg/path/path_util.h +++ - 2024-05-10 13:52:17.808928316 +0200 @@ -0,0 +1,41 @@ +/* +** OSSP path - Filesystem Path Manipulation +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** +** 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.h: internal utility API +*/ + +#ifndef __PATH_UTIL_H__ +#define __PATH_UTIL_H__ + +int path_mvxprintf (int (*output)(void *ctx, const char *buffer, size_t bufsize), void *ctx, const char *format, va_list ap); +int path_mvsnprintf (char *buffer, size_t bufsize, const char *format, va_list ap); +int path_msnprintf (char *buffer, size_t bufsize, const char *format, ...); +char *path_mvasnprintf (const char *format, va_list ap); +char *path_masnprintf (const char *format, ...); + +#endif /* __PATH_UTIL__ */ +