From 6974bd7cc8f93d702a55eefe799bccc043aca966 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Sun, 25 Jan 2026 05:35:00 +0100 Subject: [PATCH] curlx: dedupe basename copies into `curlx_basename()` Also stop redefining system `basename()` symbol. Call `curlx_basename()` instead, and map that to `basename()` if available. Closes #20424 --- lib/Makefile.inc | 4 +- src/tool_bname.c => lib/curlx/basename.c | 39 ++++++++++++++--- src/tool_bname.h => lib/curlx/basename.h | 19 ++++---- lib/curlx/curlx.h | 3 ++ lib/mime.c | 56 +----------------------- src/Makefile.inc | 3 +- src/tool_doswin.c | 9 +--- 7 files changed, 54 insertions(+), 79 deletions(-) rename src/tool_bname.c => lib/curlx/basename.c (50%) rename src/tool_bname.h => lib/curlx/basename.h (79%) diff --git a/lib/Makefile.inc b/lib/Makefile.inc index d5c55dff6e..0146d87557 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -25,6 +25,7 @@ LIB_CURLX_CFILES = \ curlx/base64.c \ + curlx/basename.c \ curlx/dynbuf.c \ curlx/fopen.c \ curlx/inet_ntop.c \ @@ -42,8 +43,9 @@ LIB_CURLX_CFILES = \ curlx/winapi.c LIB_CURLX_HFILES = \ - curlx/binmode.h \ curlx/base64.h \ + curlx/binmode.h \ + curlx/basename.h \ curlx/curlx.h \ curlx/dynbuf.h \ curlx/fopen.h \ diff --git a/src/tool_bname.c b/lib/curlx/basename.c similarity index 50% rename from src/tool_bname.c rename to lib/curlx/basename.c index f628d819fb..27c29f3c00 100644 --- a/src/tool_bname.c +++ b/lib/curlx/basename.c @@ -21,23 +21,48 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include "tool_setup.h" +#include "../curl_setup.h" #ifndef HAVE_BASENAME -#include "tool_bname.h" +#include "basename.h" -char *tool_basename(char *path) +/* + (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 + Edition) + + The basename() function shall take the pathname pointed to by path and + return a pointer to the final component of the pathname, deleting any + trailing '/' characters. + + If the string pointed to by path consists entirely of the '/' character, + basename() shall return a pointer to the string "/". If the string pointed + to by path is exactly "//", it is implementation-defined whether '/' or "//" + is returned. + + If path is a null pointer or points to an empty string, basename() shall + return a pointer to the string ".". + + The basename() function may modify the string pointed to by path, and may + return a pointer to static storage that may then be overwritten by a + subsequent call to basename(). + + The basename() function need not be reentrant. A function that is not + required to be reentrant is not required to be thread-safe. + +*/ +char *curlx_basename(char *path) { + /* Ignore all the details above for now and make a quick and simple + implementation here */ char *s1; char *s2; s1 = strrchr(path, '/'); s2 = strrchr(path, '\\'); - if(s1 && s2) { - path = (s1 > s2) ? s1 + 1 : s2 + 1; - } + if(s1 && s2) + path = ((s1 > s2) ? s1 : s2) + 1; else if(s1) path = s1 + 1; else if(s2) @@ -46,4 +71,4 @@ char *tool_basename(char *path) return path; } -#endif /* HAVE_BASENAME */ +#endif /* !HAVE_BASENAME */ diff --git a/src/tool_bname.h b/lib/curlx/basename.h similarity index 79% rename from src/tool_bname.h rename to lib/curlx/basename.h index 4047c5cc78..287a14aa14 100644 --- a/src/tool_bname.h +++ b/lib/curlx/basename.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_TOOL_BNAME_H -#define HEADER_CURL_TOOL_BNAME_H +#ifndef HEADER_CURLX_BASENAME_H +#define HEADER_CURLX_BASENAME_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -23,14 +23,17 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include "tool_setup.h" +#include "../curl_setup.h" #ifndef HAVE_BASENAME +char *curlx_basename(char *path); +#else -char *tool_basename(char *path); +#ifdef HAVE_LIBGEN_H +#include +#endif -#define basename(x) tool_basename(x) +#define curlx_basename(x) basename(x) +#endif /* !HAVE_BASENAME */ -#endif /* HAVE_BASENAME */ - -#endif /* HEADER_CURL_TOOL_BNAME_H */ +#endif /* HEADER_CURLX_BASENAME_H */ diff --git a/lib/curlx/curlx.h b/lib/curlx/curlx.h index 817acb07cd..1733625fd8 100644 --- a/lib/curlx/curlx.h +++ b/lib/curlx/curlx.h @@ -31,6 +31,9 @@ * be. */ +#include "basename.h" +/* for curlx_basename() function */ + #include "binmode.h" /* "binmode.h" provides macro CURLX_SET_BINMODE() */ diff --git a/lib/mime.c b/lib/mime.c index 4d8177c066..45a93eb3fc 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -31,6 +31,7 @@ struct Curl_easy; #include "curl_trc.h" #include "transfer.h" #include "strdup.h" +#include "curlx/basename.h" #include "curlx/strcopy.h" #include "curlx/fopen.h" #include "curlx/base64.h" @@ -39,10 +40,6 @@ struct Curl_easy; !defined(CURL_DISABLE_SMTP) || \ !defined(CURL_DISABLE_IMAP)) -#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) -#include -#endif - #include "rand.h" #include "slist.h" #include "curlx/dynbuf.h" @@ -182,55 +179,6 @@ static FILE *vmsfopenread(const char *file, const char *mode) #define fopen_read vmsfopenread #endif /* !__VMS */ -#ifndef HAVE_BASENAME -/* - (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 - Edition) - - The basename() function shall take the pathname pointed to by path and - return a pointer to the final component of the pathname, deleting any - trailing '/' characters. - - If the string pointed to by path consists entirely of the '/' character, - basename() shall return a pointer to the string "/". If the string pointed - to by path is exactly "//", it is implementation-defined whether '/' or "//" - is returned. - - If path is a null pointer or points to an empty string, basename() shall - return a pointer to the string ".". - - The basename() function may modify the string pointed to by path, and may - return a pointer to static storage that may then be overwritten by a - subsequent call to basename(). - - The basename() function need not be reentrant. A function that is not - required to be reentrant is not required to be thread-safe. - -*/ -static char *Curl_basename(char *path) -{ - /* Ignore all the details above for now and make a quick and simple - implementation here */ - char *s1; - char *s2; - - s1 = strrchr(path, '/'); - s2 = strrchr(path, '\\'); - - if(s1 && s2) { - path = (s1 > s2 ? s1 : s2) + 1; - } - else if(s1) - path = s1 + 1; - else if(s2) - path = s2 + 1; - - return path; -} - -#define basename(x) Curl_basename(x) -#endif /* !HAVE_BASENAME */ - /* Set readback state. */ static void mimesetstate(struct mime_state *state, enum mimestate tok, void *ptr) @@ -319,7 +267,7 @@ static char *strippath(const char *fullfile) the buffer it works on */ if(!filename) return NULL; - base = curlx_strdup(basename(filename)); + base = curlx_strdup(curlx_basename(filename)); curlx_free(filename); /* free temporary buffer */ diff --git a/src/Makefile.inc b/src/Makefile.inc index 4e8efdd926..d17d92f829 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -34,6 +34,7 @@ # the official API, but we reuse the code here to avoid duplication. CURLX_CFILES = \ ../lib/curlx/base64.c \ + ../lib/curlx/basename.c \ ../lib/curlx/dynbuf.c \ ../lib/curlx/fopen.c \ ../lib/curlx/multibyte.c \ @@ -76,7 +77,6 @@ CURL_CFILES = \ config2setopts.c \ slist_wc.c \ terminal.c \ - tool_bname.c \ tool_cb_dbg.c \ tool_cb_hdr.c \ tool_cb_prg.c \ @@ -122,7 +122,6 @@ CURL_HFILES = \ config2setopts.h \ slist_wc.h \ terminal.h \ - tool_bname.h \ tool_cb_dbg.h \ tool_cb_hdr.h \ tool_cb_prg.h \ diff --git a/src/tool_doswin.c b/src/tool_doswin.c index f4fb9f8e83..e1ba4f8fc1 100644 --- a/src/tool_doswin.c +++ b/src/tool_doswin.c @@ -25,10 +25,6 @@ #if defined(_WIN32) || defined(MSDOS) -#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) -# include -#endif - #ifdef _WIN32 # include # undef PATH_MAX @@ -41,7 +37,6 @@ #endif #include "tool_cfgable.h" -#include "tool_bname.h" #include "tool_doswin.h" #include "tool_msgs.h" @@ -327,7 +322,7 @@ static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, memcpy(buffer, file_name, len + 1); - base = basename(buffer); + base = curlx_basename(buffer); /* Rename reserved device names that are known to be accessible without \\.\ Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS @@ -378,7 +373,7 @@ static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, /* the basename pointer must be updated since the path has expanded */ if(p == buffer) - base = basename(buffer); + base = curlx_basename(buffer); } /* This is the legacy portion from rename_if_dos_device_name that checks for