]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
curlx: add and use `curlx_freopen()`
authorViktor Szakats <commit@vsz.me>
Wed, 19 Nov 2025 00:10:48 +0000 (01:10 +0100)
committerViktor Szakats <commit@vsz.me>
Wed, 19 Nov 2025 21:04:53 +0000 (22:04 +0100)
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 <filename>` curl command-line option on Windows.

Also add to checksrc.

Follow-up to 2f17a9b654121dd1ecf4fc043c6d08a9da3522db #10673

Closes #19598

docs/internals/CHECKSRC.md
lib/curl_setup.h
lib/curlx/fopen.c
lib/curlx/fopen.h
lib/memdebug.c
scripts/checksrc.pl
src/tool_stderr.c

index 9c4f1428791e39b05eeaf5cbc19f41854c4cc986..1740b2bef5915ac1f0c54adf3a7cbc6b1d5edc61 100644 (file)
@@ -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
index f5b9111f610387f08f42d1929057791729ee917e..0df96d5efd28374a6fafe87bf6632365717d833b 100644 (file)
@@ -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);
index a5311874b8aee554a0697d1bd15eb4adfadf8d6d..333eff7de7e2f6b98c63b4283358fd87f2f81d87 100644 (file)
@@ -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;
index da9eb55ec9dd7c67b52d4154434e4862c27881eb..eeb3fda9469ca8839e4213c7c88074c34ac0f1e0 100644 (file)
@@ -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
index 11e924a55b099653daee61b9abbdea06275b73f5..758c7b6aa7e29f75a4815db6d762586eccd70c51 100644 (file)
@@ -29,7 +29,7 @@
 #include <curl/curl.h>
 
 #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;
 }
index 5f9ea335268315ef5d3f840dddb5867809e3f9c6..c9f008f1a1dfd5fdadcef8ae778aa36d0da55f6c 100755 (executable)
@@ -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",
index 1116c30092554b6e57a4bce4bb50183c5dfeaf3b..8812f8bf8e528af7315572557a5801502ae75a41 100644 (file)
@@ -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);