From 661ed94d9b05653ea72a5ac2bfadd6f2178e4768 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 10 Aug 2023 10:07:22 +0200 Subject: [PATCH] path: new funcs to merge paths Take windows directory separators into account. Path is not checked or "resolved". (cherry picked from commit 228caa640b3f961fd13ca8744cbbee789116bd30) --- src/util-error.c | 2 ++ src/util-error.h | 2 ++ src/util-path.c | 80 +++++++++++++++++++++++++++++++++++++++--------- src/util-path.h | 10 +++++- 4 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/util-error.c b/src/util-error.c index 975e12ae9eef..d516aca57d89 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -381,6 +381,8 @@ const char * SCErrorToString(SCError err) CASE_CODE(SC_ERR_HASH_ADD); CASE_CODE(SC_ERR_SIGNAL); CASE_CODE(SC_WARN_REFCNT); + CASE_CODE(SC_ERR_PATH_JOIN); + CASE_CODE(SC_ERR_PATH_RESOLVE); CASE_CODE (SC_ERR_MAX); } diff --git a/src/util-error.h b/src/util-error.h index 398aee9eebe4..841cc128a935 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -371,6 +371,8 @@ typedef enum { SC_ERR_HASH_ADD, SC_ERR_SIGNAL, SC_WARN_REFCNT, + SC_ERR_PATH_JOIN, + SC_ERR_PATH_RESOLVE, SC_ERR_MAX } SCError; diff --git a/src/util-path.c b/src/util-path.c index 22d5e94e0b22..7063aba595b5 100644 --- a/src/util-path.c +++ b/src/util-path.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2012 Open Information Security Foundation +/* Copyright (C) 2007-2023 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -72,36 +72,86 @@ int PathIsRelative(const char *path) return PathIsAbsolute(path) ? 0 : 1; } +int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname) +{ + char path[PATH_MAX]; + if (dir == NULL || strlen(dir) == 0) + return -1; + + size_t r = strlcpy(path, dir, sizeof(path)); + if (r >= sizeof(path)) { + return -1; + } + +#if defined OS_WIN32 || defined __CYGWIN__ + if (path[strlen(path) - 1] != '\\') + r = strlcat(path, "\\\\", sizeof(path)); +#else + if (path[strlen(path) - 1] != '/') + r = strlcat(path, "/", sizeof(path)); +#endif + if (r >= sizeof(path)) { + return -1; + } + r = strlcat(path, fname, sizeof(path)); + if (r >= sizeof(path)) { + return -1; + } + r = strlcpy(out_buf, path, buf_size); + if (r >= buf_size) { + return -1; + } + + return 0; +} + +char *PathMergeAlloc(const char *const dir, const char *const fname) +{ + char path[PATH_MAX]; + if (PathMerge(path, sizeof(path), dir, fname) != 0) + return NULL; + + char *ret = SCStrdup(path); + if (ret == NULL) + return NULL; + + return ret; +} + /** * \brief Wrapper to join a directory and filename and resolve using realpath * _fullpath is used for WIN32 * * \param out_buf output buffer. Up to PATH_MAX will be written. Unchanged on exit failure. - * \param buf_len length of output buffer + * \param buf_size length of output buffer, must be PATH_MAX * \param dir the directory * \param fname the filename * - * \retval TM_ECODE_OK on success - * \retval TM_ECODE_FAILED on failure + * \retval 0 on success + * \retval -1 on failure */ -TmEcode PathJoin (char *out_buf, uint16_t buf_len, const char *const dir, const char *const fname) +int PathJoin(char *out_buf, size_t buf_size, const char *const dir, const char *const fname) { SCEnter(); - uint16_t max_path_len = MAX(buf_len, PATH_MAX); - int bytes_written = snprintf(out_buf, max_path_len, "%s%c%s", dir, DIRECTORY_SEPARATOR, fname); - if (bytes_written <= 0) { - SCLogError(SC_ERR_SPRINTF, "Could not join filename to path"); - SCReturnInt(TM_ECODE_FAILED); + if (buf_size != PATH_MAX) { + return -1; + } + if (PathMerge(out_buf, buf_size, dir, fname) != 0) { + SCLogError(SC_ERR_PATH_JOIN, "Could not join filename to path"); + return -1; } char *tmp_buf = SCRealPath(out_buf, NULL); if (tmp_buf == NULL) { - SCLogError(SC_ERR_SPRINTF, "Error resolving path: %s", strerror(errno)); - SCReturnInt(TM_ECODE_FAILED); + SCLogError(SC_ERR_PATH_RESOLVE, "Error resolving path: %s", strerror(errno)); + return -1; } - memset(out_buf, 0, buf_len); - strlcpy(out_buf, tmp_buf, max_path_len); + memset(out_buf, 0, buf_size); + size_t ret = strlcpy(out_buf, tmp_buf, buf_size); free(tmp_buf); - SCReturnInt(TM_ECODE_OK); + if (ret >= buf_size) { + return -1; + } + return 0; } /** diff --git a/src/util-path.h b/src/util-path.h index b8a5dd25939d..141b6fc2472e 100644 --- a/src/util-path.h +++ b/src/util-path.h @@ -35,6 +35,12 @@ typedef struct stat SCStat; #define SCStatFn(pathname, statbuf) stat((pathname), (statbuf)) #endif +#if defined OS_WIN32 || defined __CYGWIN__ +#define PATH_SEPARATOR_SIZE 2 +#else +#define PATH_SEPARATOR_SIZE 1 +#endif + #ifndef HAVE_NON_POSIX_MKDIR #define SCMkDir(a, b) mkdir(a, b) #else @@ -43,7 +49,9 @@ typedef struct stat SCStat; int PathIsAbsolute(const char *); int PathIsRelative(const char *); -TmEcode PathJoin (char *out_buf, uint16_t buf_len, const char *const dir, const char *const fname); +int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname); +char *PathMergeAlloc(const char *const dir, const char *const fname); +int PathJoin(char *out_buf, size_t buf_len, const char *const dir, const char *const fname); int SCDefaultMkDir(const char *path); int SCCreateDirectoryTree(const char *path, const bool final); bool SCPathExists(const char *path);