From: Viktor Szakats Date: Wed, 19 Nov 2025 00:10:48 +0000 (+0100) Subject: curlx: add and use `curlx_freopen()` X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3d80d37cf0bdfc25645bd150c692d122e94ef1cb;p=thirdparty%2Fcurl.git curlx: add and use `curlx_freopen()` To complement the existing `curlx_fopen()` internal API. It's used by the curl's `--stderr` option. `curlx_freopen()` adds two features to the bare `freopen()`: - tracing for debug-enabled builds. - Unicode and long-filename support for Windows builds. In effect this adds long-filename and enables Unicode support for the `--stderr ` curl command-line option on Windows. Also add to checksrc. Follow-up to 2f17a9b654121dd1ecf4fc043c6d08a9da3522db #10673 Closes #19598 --- diff --git a/docs/internals/CHECKSRC.md b/docs/internals/CHECKSRC.md index 9c4f142879..1740b2bef5 100644 --- a/docs/internals/CHECKSRC.md +++ b/docs/internals/CHECKSRC.md @@ -76,7 +76,8 @@ warnings are: - `EXCLAMATIONSPACE`: space found after exclamations mark -- `FOPENMODE`: `curlx_fopen()` needs a macro for the mode string, use it +- `FOPENMODE`: `curlx_fopen()`, `curlx_freopen()` need a macro for the mode + string, use it - `INDENTATION`: detected a wrong start column for code. Note that this warning only checks some specific places and can certainly miss many bad diff --git a/lib/curl_setup.h b/lib/curl_setup.h index f5b9111f61..0df96d5efd 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -1041,6 +1041,9 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode, int line, const char *source); +CURL_EXTERN ALLOC_FUNC + FILE *curl_dbg_freopen(const char *file, const char *mode, FILE *fh, + int line, const char *source); CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode, int line, const char *source); diff --git a/lib/curlx/fopen.c b/lib/curlx/fopen.c index a5311874b8..333eff7de7 100644 --- a/lib/curlx/fopen.c +++ b/lib/curlx/fopen.c @@ -282,6 +282,40 @@ FILE *curlx_win32_fopen(const char *filename, const char *mode) return result; } +FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fp) +{ + FILE *result = NULL; + TCHAR *fixed = NULL; + const TCHAR *target = NULL; + +#ifdef _UNICODE + wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename); + wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode); + if(filename_w && mode_w) { + if(fix_excessive_path(filename_w, &fixed)) + target = fixed; + else + target = filename_w; + result = _wfreopen(target, mode_w, fp); + } + else + /* !checksrc! disable ERRNOVAR 1 */ + errno = EINVAL; + curlx_unicodefree(filename_w); + curlx_unicodefree(mode_w); +#else + if(fix_excessive_path(filename, &fixed)) + target = fixed; + else + target = filename; + /* !checksrc! disable BANNEDFUNC 1 */ + result = freopen(target, mode, fp); +#endif + + (free)(fixed); + return result; +} + int curlx_win32_stat(const char *path, struct_stat *buffer) { int result = -1; diff --git a/lib/curlx/fopen.h b/lib/curlx/fopen.h index da9eb55ec9..eeb3fda946 100644 --- a/lib/curlx/fopen.h +++ b/lib/curlx/fopen.h @@ -36,23 +36,29 @@ int curlx_fseek(void *stream, curl_off_t offset, int whence); #ifdef _WIN32 FILE *curlx_win32_fopen(const char *filename, const char *mode); +FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fh); int curlx_win32_stat(const char *path, struct_stat *buffer); int curlx_win32_open(const char *filename, int oflag, ...); -#define CURLX_FOPEN_LOW(fname, mode) curlx_win32_fopen(fname, mode) -#define curlx_stat(fname, stp) curlx_win32_stat(fname, stp) -#define curlx_open curlx_win32_open +#define CURLX_FOPEN_LOW(fname, mode) curlx_win32_fopen(fname, mode) +#define CURLX_FREOPEN_LOW(fname, mode, fh) curlx_win32_freopen(fname, mode, fh) +#define curlx_stat(fname, stp) curlx_win32_stat(fname, stp) +#define curlx_open curlx_win32_open #else -#define CURLX_FOPEN_LOW fopen -#define curlx_stat(fname, stp) stat(fname, stp) -#define curlx_open open +#define CURLX_FOPEN_LOW fopen +#define CURLX_FREOPEN_LOW freopen +#define curlx_stat(fname, stp) stat(fname, stp) +#define curlx_open open #endif #ifdef CURLDEBUG #define curlx_fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) +#define curlx_freopen(file,mode,fh) \ + curl_dbg_freopen(file,mode,fh,__LINE__,__FILE__) #define curlx_fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) #define curlx_fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) #else #define curlx_fopen CURLX_FOPEN_LOW +#define curlx_freopen CURLX_FREOPEN_LOW #define curlx_fdopen fdopen #define curlx_fclose fclose #endif diff --git a/lib/memdebug.c b/lib/memdebug.c index 11e924a55b..758c7b6aa7 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -29,7 +29,7 @@ #include #include "urldata.h" -#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW() */ +#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW(), CURLX_FREOPEN_LOW() */ /* The last 2 #include files should be in this order */ #include "curl_memory.h" @@ -424,7 +424,19 @@ FILE *curl_dbg_fopen(const char *file, const char *mode, FILE *res = CURLX_FOPEN_LOW(file, mode); if(source) curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", - source, line, file, mode, (void *)res); + source, line, file, mode, (void *)res); + + return res; +} + +ALLOC_FUNC +FILE *curl_dbg_freopen(const char *file, const char *mode, FILE *fh, + int line, const char *source) +{ + FILE *res = CURLX_FREOPEN_LOW(file, mode, fh); + if(source) + curl_dbg_log("FILE %s:%d freopen(\"%s\",\"%s\",%p) = %p\n", + source, line, file, mode, (void *)fh, (void *)res); return res; } diff --git a/scripts/checksrc.pl b/scripts/checksrc.pl index 5f9ea33526..c9f008f1a1 100755 --- a/scripts/checksrc.pl +++ b/scripts/checksrc.pl @@ -106,6 +106,7 @@ my %banfunc = ( "fclose" => 1, "fdopen" => 1, "fopen" => 1, + "freopen" => 1, "open" => 1, "stat" => 1, ); @@ -961,7 +962,7 @@ sub scanfile { } # scan for use of non-binary fopen without the macro - if($l =~ /^(.*\W)(curlx_fopen|CURLX_FOPEN_LOW)\s*\([^,]*, *\"([^"]*)/) { + if($l =~ /^(.*\W)(curlx_fopen|CURLX_FOPEN_LOW|curlx_freopen|CURLX_FREOPEN_LOW)\s*\([^,]*, *\"([^"]*)/) { my $mode = $3; if($mode !~ /b/) { checkwarn("FOPENMODE", diff --git a/src/tool_stderr.c b/src/tool_stderr.c index 1116c30092..8812f8bf8e 100644 --- a/src/tool_stderr.c +++ b/src/tool_stderr.c @@ -60,7 +60,7 @@ void tool_set_stderr_file(const char *filename) /* freopen the actual stderr (stdio.h stderr) instead of tool_stderr since the latter may be set to stdout. */ /* !checksrc! disable STDERR 1 */ - fp = freopen(filename, FOPEN_WRITETEXT, stderr); + fp = curlx_freopen(filename, FOPEN_WRITETEXT, stderr); if(!fp) { /* stderr may have been closed by freopen. there is nothing to be done. */ DEBUGASSERT(0);