From 20142f5d06f7120ba94cbcc25c998e8d81aec85b Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Sun, 14 Sep 2025 15:34:18 +0200 Subject: [PATCH] build: avoid overriding system symbols for fopen functions By introducing wrappers for them in the curlx namespace: `curlx_fopen()`, `curlx_fdopen()`, `curlx_fclose()`. The undefine/redefine/`(function)()` methods broke on systems implementing these functions as macros. E.g. AIX 32-bit's `fopen()`. Also: - rename `lib/fopen.*` to `lib/curl_fopen.*` (for `Curl_fopen()`) to make room for the newly added `curlx/fopen.h`. - curlx: move file-related functions from `multibyte.c` to `fopen.c`. - tests/server: stop using the curl-specific `fopen()` implementation on Windows. Unicode isn't used by runtests, and it isn't critical to run tests on longs path. It can be re-enabled if this becomes necessary, or if the wrapper receives a feature that's critical for test servers. Reported-by: Andrew Kirillov Bug: https://github.com/curl/curl/issues/18510#issuecomment-3274393640 Follow-up to bf7375ecc50e857760b0d0a668c436e208a400bd #18503 Follow-up to 9863599d69b79d290928a89bf9160f4e4e023d4e #18502 Follow-up to 3bb5e58c105d7be450b667858d1b8e7ae3ded555 #17827 Closes #18634 --- .github/scripts/verify-examples.pl | 4 +- docs/examples/.checksrc | 3 + docs/internals/CHECKSRC.md | 2 +- lib/Makefile.inc | 6 +- lib/altsvc.c | 8 +- lib/cookie.c | 10 +- lib/{fopen.c => curl_fopen.c} | 8 +- lib/{fopen.h => curl_fopen.h} | 2 + lib/curl_mem_undef.h | 11 - lib/curl_setup.h | 3 - lib/curlx/curlx.h | 3 + lib/curlx/fopen.c | 310 +++++++++++++++++++++++++++++ lib/curlx/fopen.h | 48 +++++ lib/curlx/multibyte.c | 273 ------------------------- lib/hsts.c | 8 +- lib/memdebug.c | 24 +-- lib/memdebug.h | 7 - lib/mime.c | 15 +- lib/netrc.c | 5 +- lib/vtls/gtls.c | 5 +- lib/vtls/keylog.c | 7 +- lib/vtls/rustls.c | 7 +- lib/vtls/schannel.c | 5 +- lib/vtls/vtls.c | 5 +- scripts/checksrc.pl | 7 +- src/Makefile.inc | 2 + src/tool_cb_dbg.c | 2 +- src/tool_cb_wrt.c | 4 +- src/tool_cfgable.c | 2 +- src/tool_easysrc.c | 4 +- src/tool_formparse.c | 4 +- src/tool_getparam.c | 24 +-- src/tool_ipfs.c | 6 +- src/tool_operate.c | 34 ++-- src/tool_parsecfg.c | 6 +- src/tool_ssls.c | 8 +- src/tool_stderr.c | 4 +- src/tool_util.c | 2 +- src/tool_writeout.c | 12 +- src/var.c | 4 +- tests/data/test1185 | 4 +- tests/libtest/Makefile.inc | 1 + tests/libtest/cli_h2_serverpush.c | 10 +- tests/libtest/cli_hx_download.c | 4 +- tests/libtest/cli_hx_upload.c | 4 +- tests/libtest/lib500.c | 4 +- tests/libtest/lib505.c | 16 +- tests/libtest/lib518.c | 4 +- tests/libtest/lib525.c | 8 +- tests/libtest/lib537.c | 4 +- tests/libtest/lib541.c | 12 +- tests/libtest/lib566.c | 4 +- tests/libtest/lib568.c | 6 +- tests/libtest/lib569.c | 8 +- tests/libtest/lib571.c | 8 +- tests/libtest/lib572.c | 6 +- tests/libtest/lib578.c | 4 +- tests/libtest/lib579.c | 8 +- tests/libtest/lib582.c | 8 +- tests/libtest/lib591.c | 6 +- tests/libtest/lib599.c | 4 +- tests/libtest/lib678.c | 4 +- tests/server/.checksrc | 2 + tests/server/Makefile.inc | 1 + tests/unit/unit3200.c | 8 +- 65 files changed, 568 insertions(+), 484 deletions(-) rename lib/{fopen.c => curl_fopen.c} (96%) rename lib/{fopen.h => curl_fopen.h} (97%) create mode 100644 lib/curlx/fopen.c create mode 100644 lib/curlx/fopen.h diff --git a/.github/scripts/verify-examples.pl b/.github/scripts/verify-examples.pl index 27c4de6db8..a8dd08d182 100755 --- a/.github/scripts/verify-examples.pl +++ b/.github/scripts/verify-examples.pl @@ -63,9 +63,9 @@ sub extract { elsif($syn == 1) { if(/^~~~/) { $syn++; - print O "/* !checksrc! disable UNUSEDIGNORE all */\n"; + print O "/* !checksrc! disable BANNEDFUNC all */\n"; # for fopen() print O "/* !checksrc! disable COPYRIGHT all */\n"; - print O "/* !checksrc! disable FOPENMODE all */\n"; + print O "/* !checksrc! disable UNUSEDIGNORE all */\n"; printf O "#line %d \"$f\"\n", $iline+1; } } diff --git a/docs/examples/.checksrc b/docs/examples/.checksrc index 0b626e6570..e0b6c43da9 100644 --- a/docs/examples/.checksrc +++ b/docs/examples/.checksrc @@ -1,3 +1,6 @@ +allowfunc fclose +allowfunc fdopen +allowfunc fopen allowfunc gmtime allowfunc localtime allowfunc socket diff --git a/docs/internals/CHECKSRC.md b/docs/internals/CHECKSRC.md index 16eb96c75b..9c4f142879 100644 --- a/docs/internals/CHECKSRC.md +++ b/docs/internals/CHECKSRC.md @@ -76,7 +76,7 @@ warnings are: - `EXCLAMATIONSPACE`: space found after exclamations mark -- `FOPENMODE`: `fopen()` needs a macro for the mode string, use it +- `FOPENMODE`: `curlx_fopen()` needs 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/Makefile.inc b/lib/Makefile.inc index 6391eb2c43..1447e53a1e 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -26,6 +26,7 @@ LIB_CURLX_CFILES = \ curlx/base64.c \ curlx/dynbuf.c \ + curlx/fopen.c \ curlx/inet_ntop.c \ curlx/inet_pton.c \ curlx/multibyte.c \ @@ -43,6 +44,7 @@ LIB_CURLX_HFILES = \ curlx/base64.h \ curlx/curlx.h \ curlx/dynbuf.h \ + curlx/fopen.h \ curlx/inet_ntop.h \ curlx/inet_pton.h \ curlx/multibyte.h \ @@ -157,6 +159,7 @@ LIB_CFILES = \ curl_des.c \ curl_endian.c \ curl_fnmatch.c \ + curl_fopen.c \ curl_get_line.c \ curl_gethostname.c \ curl_gssapi.c \ @@ -181,7 +184,6 @@ LIB_CFILES = \ fake_addrinfo.c \ file.c \ fileinfo.c \ - fopen.c \ formdata.c \ ftp.c \ ftplistparser.c \ @@ -286,6 +288,7 @@ LIB_HFILES = \ curl_des.h \ curl_endian.h \ curl_fnmatch.h \ + curl_fopen.h \ curl_get_line.h \ curl_gethostname.h \ curl_gssapi.h \ @@ -320,7 +323,6 @@ LIB_HFILES = \ fake_addrinfo.h \ file.h \ fileinfo.h \ - fopen.h \ formdata.h \ ftp.h \ ftplistparser.h \ diff --git a/lib/altsvc.c b/lib/altsvc.c index c7448692fb..7e4c4b5c25 100644 --- a/lib/altsvc.c +++ b/lib/altsvc.c @@ -31,11 +31,11 @@ #include #include "urldata.h" #include "altsvc.h" +#include "curl_fopen.h" #include "curl_get_line.h" #include "parsedate.h" #include "sendf.h" #include "curlx/warnless.h" -#include "fopen.h" #include "rename.h" #include "strdup.h" #include "curlx/inet_pton.h" @@ -227,7 +227,7 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) if(!asi->filename) return CURLE_OUT_OF_MEMORY; - fp = fopen(file, FOPEN_READTEXT); + fp = curlx_fopen(file, FOPEN_READTEXT); if(fp) { struct dynbuf buf; curlx_dyn_init(&buf, MAX_ALTSVC_LINE); @@ -238,7 +238,7 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) altsvc_add(asi, lineptr); } curlx_dyn_free(&buf); /* free the line buffer */ - fclose(fp); + curlx_fclose(fp); } return result; } @@ -391,7 +391,7 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data, if(result) break; } - fclose(out); + curlx_fclose(out); if(!result && tempstore && Curl_rename(tempstore, file)) result = CURLE_WRITE_ERROR; diff --git a/lib/cookie.c b/lib/cookie.c index 90d375a761..c5fbe1344d 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -80,11 +80,11 @@ Example set of cookies: #include "slist.h" #include "share.h" #include "strcase.h" +#include "curl_fopen.h" #include "curl_get_line.h" #include "curl_memrchr.h" #include "parsedate.h" #include "rename.h" -#include "fopen.h" #include "strdup.h" #include "llist.h" #include "curlx/strparse.h" @@ -1195,7 +1195,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, if(!strcmp(file, "-")) fp = stdin; else { - fp = fopen(file, "rb"); + fp = curlx_fopen(file, "rb"); if(!fp) infof(data, "WARNING: failed to open cookie file \"%s\"", file); else @@ -1228,7 +1228,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, remove_expired(ci); if(handle) - fclose(handle); + curlx_fclose(handle); } data->state.cookie_engine = TRUE; } @@ -1583,7 +1583,7 @@ static CURLcode cookie_output(struct Curl_easy *data, } if(!use_stdout) { - fclose(out); + curlx_fclose(out); out = NULL; if(tempstore && Curl_rename(tempstore, filename)) { unlink(tempstore); @@ -1602,7 +1602,7 @@ static CURLcode cookie_output(struct Curl_easy *data, error: if(out && !use_stdout) - fclose(out); + curlx_fclose(out); free(tempstore); return error; } diff --git a/lib/fopen.c b/lib/curl_fopen.c similarity index 96% rename from lib/fopen.c rename to lib/curl_fopen.c index b28977317a..13acd299c0 100644 --- a/lib/fopen.c +++ b/lib/curl_fopen.c @@ -33,7 +33,7 @@ #include "urldata.h" #include "rand.h" -#include "fopen.h" +#include "curl_fopen.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -102,7 +102,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, char *dir = NULL; *tempname = NULL; - *fh = fopen(filename, FOPEN_WRITETEXT); + *fh = curlx_fopen(filename, FOPEN_WRITETEXT); if(!*fh) goto fail; if( @@ -114,7 +114,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, || !S_ISREG(sb.st_mode)) { return CURLE_OK; } - fclose(*fh); + curlx_fclose(*fh); *fh = NULL; result = Curl_rand_alnum(data, randbuf, sizeof(randbuf)); @@ -144,7 +144,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, if(fd == -1) goto fail; - *fh = fdopen(fd, FOPEN_WRITETEXT); + *fh = curlx_fdopen(fd, FOPEN_WRITETEXT); if(!*fh) goto fail; diff --git a/lib/fopen.h b/lib/curl_fopen.h similarity index 97% rename from lib/fopen.h rename to lib/curl_fopen.h index e3a919d073..a3dc1382bc 100644 --- a/lib/fopen.h +++ b/lib/curl_fopen.h @@ -24,6 +24,8 @@ * ***************************************************************************/ +#include "curlx/fopen.h" + CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, FILE **fh, char **tempname); diff --git a/lib/curl_mem_undef.h b/lib/curl_mem_undef.h index a70a9fcf53..2be114cbd5 100644 --- a/lib/curl_mem_undef.h +++ b/lib/curl_mem_undef.h @@ -33,16 +33,5 @@ #undef Curl_tcsdup #endif -#ifdef CURLDEBUG - -#undef fopen -#ifdef CURL_FOPEN -#define fopen(fname, mode) CURL_FOPEN(fname, mode) -#endif -#undef fdopen -#undef fclose - -#endif /* CURLDEBUG */ - #undef HEADER_CURL_MEMORY_H #undef HEADER_CURL_MEMDEBUG_H diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 55c65c99f6..b3c19a95ef 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -509,11 +509,8 @@ # ifndef UNDER_CE int curlx_win32_stat(const char *path, struct_stat *buffer); int curlx_win32_open(const char *filename, int oflag, ...); - FILE *curlx_win32_fopen(const char *filename, const char *mode); # define stat(fname, stp) curlx_win32_stat(fname, stp) # define open curlx_win32_open -# define CURL_FOPEN(fname, mode) curlx_win32_fopen(fname, mode) -# define fopen(fname, mode) CURL_FOPEN(fname, mode) # endif #elif defined(__DJGPP__) /* Requires DJGPP 2.04 */ diff --git a/lib/curlx/curlx.h b/lib/curlx/curlx.h index 9f7bd3a975..33ac72e8e1 100644 --- a/lib/curlx/curlx.h +++ b/lib/curlx/curlx.h @@ -64,6 +64,9 @@ #include "dynbuf.h" /* The curlx_dyn_* functions */ +#include "fopen.h" +/* The curlx_f* functions */ + #include "base64.h" #include "timeval.h" #include "timediff.h" diff --git a/lib/curlx/fopen.c b/lib/curlx/fopen.c new file mode 100644 index 0000000000..22c7259c70 --- /dev/null +++ b/lib/curlx/fopen.c @@ -0,0 +1,310 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* + * This file is 'mem-include-scan' clean, which means its memory allocations + * are not tracked by the curl memory tracker memdebug, so they must not use + * `CURLDEBUG` macro replacements in memdebug.h for free, malloc, etc. To avoid + * these macro replacements, wrap the names in parentheses to call the original + * versions: `ptr = (malloc)(123)`, `(free)(ptr)`, etc. + */ + +#include "../curl_setup.h" + +#if defined(_WIN32) && !defined(UNDER_CE) + +#include "fopen.h" +#include "multibyte.h" + +/* declare GetFullPathNameW for mingw-w64 UWP builds targeting old windows */ +#if defined(CURL_WINDOWS_UWP) && defined(__MINGW32__) && \ + (_WIN32_WINNT < _WIN32_WINNT_WIN10) +WINBASEAPI DWORD WINAPI GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR *); +#endif + +/* Fix excessive paths (paths that exceed MAX_PATH length of 260). + * + * This is a helper function to fix paths that would exceed the MAX_PATH + * limitation check done by Windows APIs. It does so by normalizing the passed + * in filename or path 'in' to its full canonical path, and if that path is + * longer than MAX_PATH then setting 'out' to "\\?\" prefix + that full path. + * + * For example 'in' filename255chars in current directory C:\foo\bar is + * fixed as \\?\C:\foo\bar\filename255chars for 'out' which will tell Windows + * it is ok to access that filename even though the actual full path is longer + * than 260 chars. + * + * For non-Unicode builds this function may fail sometimes because only the + * Unicode versions of some Windows API functions can access paths longer than + * MAX_PATH, for example GetFullPathNameW which is used in this function. When + * the full path is then converted from Unicode to multibyte that fails if any + * directories in the path contain characters not in the current codepage. + */ +static bool fix_excessive_path(const TCHAR *in, TCHAR **out) +{ + size_t needed, count; + const wchar_t *in_w; + wchar_t *fbuf = NULL; + + /* MS documented "approximate" limit for the maximum path length */ + const size_t max_path_len = 32767; + +#ifndef _UNICODE + wchar_t *ibuf = NULL; + char *obuf = NULL; +#endif + + *out = NULL; + + /* skip paths already normalized */ + if(!_tcsncmp(in, _T("\\\\?\\"), 4)) + goto cleanup; + +#ifndef _UNICODE + /* convert multibyte input to unicode */ + needed = mbstowcs(NULL, in, 0); + if(needed == (size_t)-1 || needed >= max_path_len) + goto cleanup; + ++needed; /* for NUL */ + ibuf = (malloc)(needed * sizeof(wchar_t)); + if(!ibuf) + goto cleanup; + count = mbstowcs(ibuf, in, needed); + if(count == (size_t)-1 || count >= needed) + goto cleanup; + in_w = ibuf; +#else + in_w = in; +#endif + + /* GetFullPathNameW returns the normalized full path in unicode. It converts + forward slashes to backslashes, processes .. to remove directory segments, + etc. Unlike GetFullPathNameA it can process paths that exceed MAX_PATH. */ + needed = (size_t)GetFullPathNameW(in_w, 0, NULL, NULL); + if(!needed || needed > max_path_len) + goto cleanup; + /* skip paths that are not excessive and do not need modification */ + if(needed <= MAX_PATH) + goto cleanup; + fbuf = (malloc)(needed * sizeof(wchar_t)); + if(!fbuf) + goto cleanup; + count = (size_t)GetFullPathNameW(in_w, (DWORD)needed, fbuf, NULL); + if(!count || count >= needed) + goto cleanup; + + /* prepend \\?\ or \\?\UNC\ to the excessively long path. + * + * c:\longpath ---> \\?\c:\longpath + * \\.\c:\longpath ---> \\?\c:\longpath + * \\?\c:\longpath ---> \\?\c:\longpath (unchanged) + * \\server\c$\longpath ---> \\?\UNC\server\c$\longpath + * + * https://learn.microsoft.com/dotnet/standard/io/file-path-formats + */ + if(!wcsncmp(fbuf, L"\\\\?\\", 4)) + ; /* do nothing */ + else if(!wcsncmp(fbuf, L"\\\\.\\", 4)) + fbuf[2] = '?'; + else if(!wcsncmp(fbuf, L"\\\\.", 3) || !wcsncmp(fbuf, L"\\\\?", 3)) { + /* Unexpected, not UNC. The formatting doc doesn't allow this AFAICT. */ + goto cleanup; + } + else { + wchar_t *temp; + + if(!wcsncmp(fbuf, L"\\\\", 2)) { + /* "\\?\UNC\" + full path without "\\" + null */ + needed = 8 + (count - 2) + 1; + if(needed > max_path_len) + goto cleanup; + + temp = (malloc)(needed * sizeof(wchar_t)); + if(!temp) + goto cleanup; + + wcsncpy(temp, L"\\\\?\\UNC\\", 8); + wcscpy(temp + 8, fbuf + 2); + } + else { + /* "\\?\" + full path + null */ + needed = 4 + count + 1; + if(needed > max_path_len) + goto cleanup; + + temp = (malloc)(needed * sizeof(wchar_t)); + if(!temp) + goto cleanup; + + wcsncpy(temp, L"\\\\?\\", 4); + wcscpy(temp + 4, fbuf); + } + + (free)(fbuf); + fbuf = temp; + } + +#ifndef _UNICODE + /* convert unicode full path to multibyte output */ + needed = wcstombs(NULL, fbuf, 0); + if(needed == (size_t)-1 || needed >= max_path_len) + goto cleanup; + ++needed; /* for NUL */ + obuf = (malloc)(needed); + if(!obuf) + goto cleanup; + count = wcstombs(obuf, fbuf, needed); + if(count == (size_t)-1 || count >= needed) + goto cleanup; + *out = obuf; + obuf = NULL; +#else + *out = fbuf; + fbuf = NULL; +#endif + +cleanup: + (free)(fbuf); +#ifndef _UNICODE + (free)(ibuf); + (free)(obuf); +#endif + return *out ? true : false; +} + +int curlx_win32_open(const char *filename, int oflag, ...) +{ + int pmode = 0; + int result = -1; + TCHAR *fixed = NULL; + const TCHAR *target = NULL; + +#ifdef _UNICODE + wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename); +#endif + + va_list param; + va_start(param, oflag); + if(oflag & O_CREAT) + pmode = va_arg(param, int); + va_end(param); + +#ifdef _UNICODE + if(filename_w) { + if(fix_excessive_path(filename_w, &fixed)) + target = fixed; + else + target = filename_w; + result = _wopen(target, oflag, pmode); + curlx_unicodefree(filename_w); + } + else + /* !checksrc! disable ERRNOVAR 1 */ + CURL_SETERRNO(EINVAL); +#else + if(fix_excessive_path(filename, &fixed)) + target = fixed; + else + target = filename; + result = _open(target, oflag, pmode); +#endif + + (free)(fixed); + return result; +} + +FILE *curlx_win32_fopen(const char *filename, const char *mode) +{ + 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 = _wfopen(target, mode_w); + } + else + /* !checksrc! disable ERRNOVAR 1 */ + CURL_SETERRNO(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 = fopen(target, mode); +#endif + + (free)(fixed); + return result; +} + +int curlx_win32_stat(const char *path, struct_stat *buffer) +{ + int result = -1; + TCHAR *fixed = NULL; + const TCHAR *target = NULL; + +#ifdef _UNICODE + wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); + if(path_w) { + if(fix_excessive_path(path_w, &fixed)) + target = fixed; + else + target = path_w; +#ifndef USE_WIN32_LARGE_FILES + result = _wstat(target, buffer); +#else + result = _wstati64(target, buffer); +#endif + curlx_unicodefree(path_w); + } + else + /* !checksrc! disable ERRNOVAR 1 */ + CURL_SETERRNO(EINVAL); +#else + if(fix_excessive_path(path, &fixed)) + target = fixed; + else + target = path; +#ifndef USE_WIN32_LARGE_FILES + result = _stat(target, buffer); +#else + result = _stati64(target, buffer); +#endif +#endif + + (free)(fixed); + return result; +} + +#endif /* _WIN32 && !UNDER_CE */ diff --git a/lib/curlx/fopen.h b/lib/curlx/fopen.h new file mode 100644 index 0000000000..2a2b079637 --- /dev/null +++ b/lib/curlx/fopen.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURLX_FOPEN_H +#define HEADER_CURLX_FOPEN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include "../curl_setup.h" + +#include "multibyte.h" + +#if defined(_WIN32) && !defined(UNDER_CE) +FILE *curlx_win32_fopen(const char *filename, const char *mode); +#define CURLX_FOPEN_LOW(fname, mode) curlx_win32_fopen(fname, mode) +#else +#define CURLX_FOPEN_LOW fopen +#endif + +#ifdef CURLDEBUG +#define curlx_fopen(file,mode) curl_dbg_fopen(file,mode,__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_fdopen fdopen +#define curlx_fclose fclose +#endif + +#endif /* HEADER_CURLX_FOPEN_H */ diff --git a/lib/curlx/multibyte.c b/lib/curlx/multibyte.c index 1c81a71ec5..9e60edf7e3 100644 --- a/lib/curlx/multibyte.c +++ b/lib/curlx/multibyte.c @@ -84,277 +84,4 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) return str_utf8; } -#ifndef UNDER_CE - -/* declare GetFullPathNameW for mingw-w64 UWP builds targeting old windows */ -#if defined(CURL_WINDOWS_UWP) && defined(__MINGW32__) && \ - (_WIN32_WINNT < _WIN32_WINNT_WIN10) -WINBASEAPI DWORD WINAPI GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR *); -#endif - -/* Fix excessive paths (paths that exceed MAX_PATH length of 260). - * - * This is a helper function to fix paths that would exceed the MAX_PATH - * limitation check done by Windows APIs. It does so by normalizing the passed - * in filename or path 'in' to its full canonical path, and if that path is - * longer than MAX_PATH then setting 'out' to "\\?\" prefix + that full path. - * - * For example 'in' filename255chars in current directory C:\foo\bar is - * fixed as \\?\C:\foo\bar\filename255chars for 'out' which will tell Windows - * it is ok to access that filename even though the actual full path is longer - * than 260 chars. - * - * For non-Unicode builds this function may fail sometimes because only the - * Unicode versions of some Windows API functions can access paths longer than - * MAX_PATH, for example GetFullPathNameW which is used in this function. When - * the full path is then converted from Unicode to multibyte that fails if any - * directories in the path contain characters not in the current codepage. - */ -static bool fix_excessive_path(const TCHAR *in, TCHAR **out) -{ - size_t needed, count; - const wchar_t *in_w; - wchar_t *fbuf = NULL; - - /* MS documented "approximate" limit for the maximum path length */ - const size_t max_path_len = 32767; - -#ifndef _UNICODE - wchar_t *ibuf = NULL; - char *obuf = NULL; -#endif - - *out = NULL; - - /* skip paths already normalized */ - if(!_tcsncmp(in, _T("\\\\?\\"), 4)) - goto cleanup; - -#ifndef _UNICODE - /* convert multibyte input to unicode */ - needed = mbstowcs(NULL, in, 0); - if(needed == (size_t)-1 || needed >= max_path_len) - goto cleanup; - ++needed; /* for NUL */ - ibuf = (malloc)(needed * sizeof(wchar_t)); - if(!ibuf) - goto cleanup; - count = mbstowcs(ibuf, in, needed); - if(count == (size_t)-1 || count >= needed) - goto cleanup; - in_w = ibuf; -#else - in_w = in; -#endif - - /* GetFullPathNameW returns the normalized full path in unicode. It converts - forward slashes to backslashes, processes .. to remove directory segments, - etc. Unlike GetFullPathNameA it can process paths that exceed MAX_PATH. */ - needed = (size_t)GetFullPathNameW(in_w, 0, NULL, NULL); - if(!needed || needed > max_path_len) - goto cleanup; - /* skip paths that are not excessive and do not need modification */ - if(needed <= MAX_PATH) - goto cleanup; - fbuf = (malloc)(needed * sizeof(wchar_t)); - if(!fbuf) - goto cleanup; - count = (size_t)GetFullPathNameW(in_w, (DWORD)needed, fbuf, NULL); - if(!count || count >= needed) - goto cleanup; - - /* prepend \\?\ or \\?\UNC\ to the excessively long path. - * - * c:\longpath ---> \\?\c:\longpath - * \\.\c:\longpath ---> \\?\c:\longpath - * \\?\c:\longpath ---> \\?\c:\longpath (unchanged) - * \\server\c$\longpath ---> \\?\UNC\server\c$\longpath - * - * https://learn.microsoft.com/dotnet/standard/io/file-path-formats - */ - if(!wcsncmp(fbuf, L"\\\\?\\", 4)) - ; /* do nothing */ - else if(!wcsncmp(fbuf, L"\\\\.\\", 4)) - fbuf[2] = '?'; - else if(!wcsncmp(fbuf, L"\\\\.", 3) || !wcsncmp(fbuf, L"\\\\?", 3)) { - /* Unexpected, not UNC. The formatting doc doesn't allow this AFAICT. */ - goto cleanup; - } - else { - wchar_t *temp; - - if(!wcsncmp(fbuf, L"\\\\", 2)) { - /* "\\?\UNC\" + full path without "\\" + null */ - needed = 8 + (count - 2) + 1; - if(needed > max_path_len) - goto cleanup; - - temp = (malloc)(needed * sizeof(wchar_t)); - if(!temp) - goto cleanup; - - wcsncpy(temp, L"\\\\?\\UNC\\", 8); - wcscpy(temp + 8, fbuf + 2); - } - else { - /* "\\?\" + full path + null */ - needed = 4 + count + 1; - if(needed > max_path_len) - goto cleanup; - - temp = (malloc)(needed * sizeof(wchar_t)); - if(!temp) - goto cleanup; - - wcsncpy(temp, L"\\\\?\\", 4); - wcscpy(temp + 4, fbuf); - } - - (free)(fbuf); - fbuf = temp; - } - -#ifndef _UNICODE - /* convert unicode full path to multibyte output */ - needed = wcstombs(NULL, fbuf, 0); - if(needed == (size_t)-1 || needed >= max_path_len) - goto cleanup; - ++needed; /* for NUL */ - obuf = (malloc)(needed); - if(!obuf) - goto cleanup; - count = wcstombs(obuf, fbuf, needed); - if(count == (size_t)-1 || count >= needed) - goto cleanup; - *out = obuf; - obuf = NULL; -#else - *out = fbuf; - fbuf = NULL; -#endif - -cleanup: - (free)(fbuf); -#ifndef _UNICODE - (free)(ibuf); - (free)(obuf); -#endif - return *out ? true : false; -} - -int curlx_win32_open(const char *filename, int oflag, ...) -{ - int pmode = 0; - int result = -1; - TCHAR *fixed = NULL; - const TCHAR *target = NULL; - -#ifdef _UNICODE - wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename); -#endif - - va_list param; - va_start(param, oflag); - if(oflag & O_CREAT) - pmode = va_arg(param, int); - va_end(param); - -#ifdef _UNICODE - if(filename_w) { - if(fix_excessive_path(filename_w, &fixed)) - target = fixed; - else - target = filename_w; - result = _wopen(target, oflag, pmode); - curlx_unicodefree(filename_w); - } - else - /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(EINVAL); -#else - if(fix_excessive_path(filename, &fixed)) - target = fixed; - else - target = filename; - result = _open(target, oflag, pmode); -#endif - - (free)(fixed); - return result; -} - -FILE *curlx_win32_fopen(const char *filename, const char *mode) -{ - 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 = _wfopen(target, mode_w); - } - else - /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(EINVAL); - curlx_unicodefree(filename_w); - curlx_unicodefree(mode_w); -#else - if(fix_excessive_path(filename, &fixed)) - target = fixed; - else - target = filename; - result = (fopen)(target, mode); -#endif - - (free)(fixed); - return result; -} - -int curlx_win32_stat(const char *path, struct_stat *buffer) -{ - int result = -1; - TCHAR *fixed = NULL; - const TCHAR *target = NULL; - -#ifdef _UNICODE - wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); - if(path_w) { - if(fix_excessive_path(path_w, &fixed)) - target = fixed; - else - target = path_w; -#ifndef USE_WIN32_LARGE_FILES - result = _wstat(target, buffer); -#else - result = _wstati64(target, buffer); -#endif - curlx_unicodefree(path_w); - } - else - /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(EINVAL); -#else - if(fix_excessive_path(path, &fixed)) - target = fixed; - else - target = path; -#ifndef USE_WIN32_LARGE_FILES - result = _stat(target, buffer); -#else - result = _stati64(target, buffer); -#endif -#endif - - (free)(fixed); - return result; -} - -#endif /* UNDER_CE */ - #endif /* _WIN32 */ diff --git a/lib/hsts.c b/lib/hsts.c index 9525158bcc..b84a470f90 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -32,10 +32,10 @@ #include "urldata.h" #include "llist.h" #include "hsts.h" +#include "curl_fopen.h" #include "curl_get_line.h" #include "sendf.h" #include "parsedate.h" -#include "fopen.h" #include "rename.h" #include "share.h" #include "strdup.h" @@ -379,7 +379,7 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h, if(result) break; } - fclose(out); + curlx_fclose(out); if(!result && tempstore && Curl_rename(tempstore, file)) result = CURLE_WRITE_ERROR; @@ -524,7 +524,7 @@ static CURLcode hsts_load(struct hsts *h, const char *file) if(!h->filename) return CURLE_OUT_OF_MEMORY; - fp = fopen(file, FOPEN_READTEXT); + fp = curlx_fopen(file, FOPEN_READTEXT); if(fp) { struct dynbuf buf; curlx_dyn_init(&buf, MAX_HSTS_LINE); @@ -542,7 +542,7 @@ static CURLcode hsts_load(struct hsts *h, const char *file) hsts_add(h, lineptr); } curlx_dyn_free(&buf); /* free the line buffer */ - fclose(fp); + curlx_fclose(fp); } return result; } diff --git a/lib/memdebug.c b/lib/memdebug.c index cffd4b2cf6..0c9d156715 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -29,6 +29,7 @@ #include #include "urldata.h" +#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW() */ /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -68,7 +69,8 @@ static void curl_dbg_cleanup(void) if(curl_dbg_logfile && curl_dbg_logfile != stderr && curl_dbg_logfile != stdout) { - (fclose)(curl_dbg_logfile); + /* !checksrc! disable BANNEDFUNC 1 */ + fclose(curl_dbg_logfile); } curl_dbg_logfile = NULL; } @@ -78,11 +80,7 @@ void curl_dbg_memdebug(const char *logname) { if(!curl_dbg_logfile) { if(logname && *logname) -#ifdef CURL_FOPEN - curl_dbg_logfile = CURL_FOPEN(logname, FOPEN_WRITETEXT); -#else - curl_dbg_logfile = (fopen)(logname, FOPEN_WRITETEXT); -#endif + curl_dbg_logfile = CURLX_FOPEN_LOW(logname, FOPEN_WRITETEXT); else curl_dbg_logfile = stderr; #ifdef MEMDEBUG_LOG_SYNC @@ -424,13 +422,7 @@ ALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode, int line, const char *source) { - FILE *res; -#ifdef CURL_FOPEN - res = CURL_FOPEN(file, mode); -#else - res = (fopen)(file, mode); -#endif - + 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); @@ -442,7 +434,8 @@ ALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode, int line, const char *source) { - FILE *res = (fdopen)(filedes, mode); + /* !checksrc! disable BANNEDFUNC 1 */ + FILE *res = fdopen(filedes, mode); if(source) curl_dbg_log("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n", source, line, filedes, mode, (void *)res); @@ -459,7 +452,8 @@ int curl_dbg_fclose(FILE *file, int line, const char *source) curl_dbg_log("FILE %s:%d fclose(%p)\n", source, line, (void *)file); - res = (fclose)(file); + /* !checksrc! disable BANNEDFUNC 1 */ + res = fclose(file); return res; } diff --git a/lib/memdebug.h b/lib/memdebug.h index 96ceb61759..c2b7fad952 100644 --- a/lib/memdebug.h +++ b/lib/memdebug.h @@ -52,12 +52,5 @@ #endif #endif /* _WIN32 */ -#undef fopen -#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) -#undef fdopen -#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) -#undef fclose -#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) - #endif /* CURLDEBUG */ #endif /* HEADER_CURL_MEMDEBUG_H */ diff --git a/lib/mime.c b/lib/mime.c index 894413be17..6ec7f69046 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -34,6 +34,7 @@ struct Curl_easy; #include "sendf.h" #include "transfer.h" #include "strdup.h" +#include "curlx/fopen.h" #include "curlx/base64.h" #if !defined(CURL_DISABLE_MIME) && \ @@ -131,7 +132,7 @@ static const char aschex[] = #ifndef __VMS #define filesize(name, stat_data) (stat_data.st_size) -#define fopen_read fopen +#define fopen_read curlx_fopen #else @@ -154,7 +155,7 @@ curl_off_t VmsRealFileSize(const char *name, int ret_stat; FILE * file; - file = fopen(name, FOPEN_READTEXT); /* VMS */ + file = curlx_fopen(name, FOPEN_READTEXT); /* VMS */ if(!file) return 0; @@ -165,7 +166,7 @@ curl_off_t VmsRealFileSize(const char *name, if(ret_stat) count += ret_stat; } - fclose(file); + curlx_fclose(file); return count; } @@ -210,10 +211,10 @@ static FILE * vmsfopenread(const char *file, const char *mode) case FAB$C_VAR: case FAB$C_VFC: case FAB$C_STMCR: - return fopen(file, FOPEN_READTEXT); /* VMS */ + return curlx_fopen(file, FOPEN_READTEXT); /* VMS */ break; default: - return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm"); + return curlx_fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm"); } } @@ -745,7 +746,7 @@ static void mime_file_free(void *ptr) curl_mimepart *part = (curl_mimepart *) ptr; if(part->fp) { - fclose(part->fp); + curlx_fclose(part->fp); part->fp = NULL; } Curl_safefree(part->data); @@ -967,7 +968,7 @@ static size_t readback_part(curl_mimepart *part, mimesetstate(&part->state, MIMESTATE_END, NULL); /* Try sparing open file descriptors. */ if(part->kind == MIMEKIND_FILE && part->fp) { - fclose(part->fp); + curlx_fclose(part->fp); part->fp = NULL; } FALLTHROUGH(); diff --git a/lib/netrc.c b/lib/netrc.c index 447ee09585..a227ffefcd 100644 --- a/lib/netrc.c +++ b/lib/netrc.c @@ -39,6 +39,7 @@ #include "netrc.h" #include "strcase.h" #include "curl_get_line.h" +#include "curlx/fopen.h" #include "curlx/strparse.h" /* The last 3 #include files should be in this order */ @@ -76,7 +77,7 @@ enum found_state { static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf) { NETRCcode ret = NETRC_FILE_MISSING; /* if it cannot open the file */ - FILE *file = fopen(filename, FOPEN_READTEXT); + FILE *file = curlx_fopen(filename, FOPEN_READTEXT); struct dynbuf linebuf; curlx_dyn_init(&linebuf, MAX_NETRC_LINE); @@ -99,7 +100,7 @@ static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf) done: curlx_dyn_free(&linebuf); if(file) - fclose(file); + curlx_fclose(file); return ret; } diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index e9252ec2a1..2db73ca2d5 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -54,6 +54,7 @@ #include "../progress.h" #include "../select.h" #include "../strdup.h" +#include "../curlx/fopen.h" #include "../curlx/warnless.h" #include "x509asn1.h" #include "../multiif.h" @@ -211,7 +212,7 @@ static gnutls_datum_t load_file(const char *file) long filelen; void *ptr; - f = fopen(file, "rb"); + f = curlx_fopen(file, "rb"); if(!f) return loaded_file; if(fseek(f, 0, SEEK_END) != 0 @@ -227,7 +228,7 @@ static gnutls_datum_t load_file(const char *file) loaded_file.data = ptr; loaded_file.size = (unsigned int)filelen; out: - fclose(f); + curlx_fclose(f); return loaded_file; } diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c index 2fd25089d9..9179d38fe7 100644 --- a/lib/vtls/keylog.c +++ b/lib/vtls/keylog.c @@ -33,6 +33,7 @@ #include "keylog.h" #include #include "../escape.h" +#include "../curlx/fopen.h" /* The last #include files should be: */ #include "../curl_memory.h" @@ -49,7 +50,7 @@ Curl_tls_keylog_open(void) if(!keylog_file_fp) { keylog_file_name = curl_getenv("SSLKEYLOGFILE"); if(keylog_file_name) { - keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); + keylog_file_fp = curlx_fopen(keylog_file_name, FOPEN_APPENDTEXT); if(keylog_file_fp) { #ifdef _WIN32 if(setvbuf(keylog_file_fp, NULL, _IONBF, 0)) @@ -57,7 +58,7 @@ Curl_tls_keylog_open(void) if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) #endif { - fclose(keylog_file_fp); + curlx_fclose(keylog_file_fp); keylog_file_fp = NULL; } } @@ -70,7 +71,7 @@ void Curl_tls_keylog_close(void) { if(keylog_file_fp) { - fclose(keylog_file_fp); + curlx_fclose(keylog_file_fp); keylog_file_fp = NULL; } } diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index a6d8a4652d..70e109212d 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -32,6 +32,7 @@ #include +#include "../curlx/fopen.h" #include "../curlx/inet_pton.h" #include "../urldata.h" #include "../sendf.h" @@ -397,7 +398,7 @@ static int read_file_into(const char *filename, struct dynbuf *out) { - FILE *f = fopen(filename, FOPEN_READTEXT); + FILE *f = curlx_fopen(filename, FOPEN_READTEXT); if(!f) { return 0; } @@ -407,14 +408,14 @@ read_file_into(const char *filename, const size_t rr = fread(buf, 1, sizeof(buf), f); if(rr == 0 || CURLE_OK != curlx_dyn_addn(out, buf, rr)) { - fclose(f); + curlx_fclose(f); return 0; } if(rr < sizeof(buf)) break; } - return fclose(f) == 0; + return curlx_fclose(f) == 0; } static void diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 8ff8029e3b..bf68321afe 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -47,6 +47,7 @@ #include "../strdup.h" #include "../strerror.h" #include "../select.h" /* for the socket readiness */ +#include "../curlx/fopen.h" #include "../curlx/inet_pton.h" /* for IP addr SNI check */ #include "../curlx/multibyte.h" #include "../curlx/warnless.h" @@ -563,7 +564,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, &cert_store_path, &cert_thumbprint_str); if(result && (data->set.ssl.primary.clientcert[0]!='\0')) - fInCert = fopen(data->set.ssl.primary.clientcert, "rb"); + fInCert = curlx_fopen(data->set.ssl.primary.clientcert, "rb"); if(result && !fInCert) { failf(data, "schannel: Failed to get certificate location" @@ -611,7 +612,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, if((!certdata) || ((int) fread(certdata, certsize, 1, fInCert) != 1)) continue_reading = FALSE; - fclose(fInCert); + curlx_fclose(fInCert); if(!continue_reading) { failf(data, "schannel: Failed to read cert file %s", data->set.ssl.primary.clientcert); diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 9872e4c24d..9e3870e470 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -68,6 +68,7 @@ #include "../progress.h" #include "../share.h" #include "../multiif.h" +#include "../curlx/fopen.h" #include "../curlx/timeval.h" #include "../curl_md5.h" #include "../curl_sha256.h" @@ -803,7 +804,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, struct dynbuf buf; char unsigned *pem_ptr = NULL; size_t left; - FILE *fp = fopen(pinnedpubkey, "rb"); + FILE *fp = curlx_fopen(pinnedpubkey, "rb"); if(!fp) return result; @@ -865,7 +866,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, end: curlx_dyn_free(&buf); Curl_safefree(pem_ptr); - fclose(fp); + curlx_fclose(fp); } return result; diff --git a/scripts/checksrc.pl b/scripts/checksrc.pl index 0012ccdae1..b737961899 100755 --- a/scripts/checksrc.pl +++ b/scripts/checksrc.pl @@ -88,6 +88,9 @@ my %banfunc = ( "send" => 1, "socket" => 1, "socketpair" => 1, + "fclose" => 1, + "fdopen" => 1, + "fopen" => 1, ); my %warnings_extended = ( @@ -919,8 +922,8 @@ sub scanfile { } # scan for use of non-binary fopen without the macro - if($l =~ /^(.*\W)fopen\s*\([^,]*, *\"([^"]*)/) { - my $mode = $2; + if($l =~ /^(.*\W)(curlx_fopen|CURLX_FOPEN_LOW)\s*\([^,]*, *\"([^"]*)/) { + my $mode = $3; if($mode !~ /b/) { checkwarn("FOPENMODE", $line, length($1), $file, $ol, diff --git a/src/Makefile.inc b/src/Makefile.inc index 1086c07feb..35f8e6fdee 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -36,6 +36,7 @@ CURLX_CFILES = \ ../lib/curlx/base64.c \ ../lib/curlx/multibyte.c \ ../lib/curlx/dynbuf.c \ + ../lib/curlx/fopen.c \ ../lib/curlx/nonblock.c \ ../lib/curlx/strparse.c \ ../lib/curlx/timediff.c \ @@ -49,6 +50,7 @@ CURLX_HFILES = \ ../lib/curlx/multibyte.h \ ../lib/curl_setup.h \ ../lib/curlx/dynbuf.h \ + ../lib/curlx/fopen.h \ ../lib/curlx/nonblock.h \ ../lib/curlx/strparse.h \ ../lib/curlx/timediff.h \ diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c index 6a587cc1cc..b454f5ca9b 100644 --- a/src/tool_cb_dbg.c +++ b/src/tool_cb_dbg.c @@ -124,7 +124,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type, /* Ok, this is somewhat hackish but we do it undocumented for now */ global->trace_stream = tool_stderr; else { - global->trace_stream = fopen(global->trace_dump, FOPEN_WRITETEXT); + global->trace_stream = curlx_fopen(global->trace_dump, FOPEN_WRITETEXT); global->trace_fopened = TRUE; } } diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c index 6fbf80753d..b4ea781739 100644 --- a/src/tool_cb_wrt.c +++ b/src/tool_cb_wrt.c @@ -55,7 +55,7 @@ bool tool_create_output_file(struct OutStruct *outs, (config->file_clobber_mode == CLOBBER_DEFAULT && !outs->is_cd_filename)) { /* open file for writing */ - file = fopen(fname, "wb"); + file = curlx_fopen(fname, "wb"); } else { int fd; @@ -92,7 +92,7 @@ bool tool_create_output_file(struct OutStruct *outs, is not needed because we would have failed earlier, in the while loop and `fd` would now be -1 */ if(fd != -1) { - file = fdopen(fd, "wb"); + file = curlx_fdopen(fd, "wb"); if(!file) close(fd); } diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index 675f4d2d9d..e2df7cf91f 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -258,7 +258,7 @@ static void free_globalconfig(void) tool_safefree(global->trace_dump); if(global->trace_fopened && global->trace_stream) - fclose(global->trace_stream); + curlx_fclose(global->trace_stream); global->trace_stream = NULL; tool_safefree(global->libcurl); diff --git a/src/tool_easysrc.c b/src/tool_easysrc.c index 223c66bdf5..bff251e6b0 100644 --- a/src/tool_easysrc.c +++ b/src/tool_easysrc.c @@ -178,7 +178,7 @@ void dumpeasysrc(void) FILE *out; bool fopened = FALSE; if(strcmp(o, "-")) { - out = fopen(o, FOPEN_WRITETEXT); + out = curlx_fopen(o, FOPEN_WRITETEXT); fopened = TRUE; } else @@ -227,7 +227,7 @@ void dumpeasysrc(void) fprintf(out, "%s\n", c); if(fopened) - fclose(out); + curlx_fclose(out); } easysrc_free(); diff --git a/src/tool_formparse.c b/src/tool_formparse.c index b5ab10a00f..f1f2f5b7e5 100644 --- a/src/tool_formparse.c +++ b/src/tool_formparse.c @@ -563,14 +563,14 @@ static int get_param_part(char endchar, endpos--; sep = *p; *endpos = '\0'; - fp = fopen(hdrfile, FOPEN_READTEXT); + fp = curlx_fopen(hdrfile, FOPEN_READTEXT); if(!fp) warnf("Cannot read from %s: %s", hdrfile, strerror(errno)); else { int i = read_field_headers(hdrfile, fp, &headers); - fclose(fp); + curlx_fclose(fp); if(i) { curl_slist_free_all(headers); return -1; diff --git a/src/tool_getparam.c b/src/tool_getparam.c index d7bdadb5d6..eed87bb807 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -627,7 +627,7 @@ static ParameterError data_urlencode(const char *nextarg, CURLX_SET_BINMODE(stdin); } else { - file = fopen(p, "rb"); + file = curlx_fopen(p, "rb"); if(!file) { errorf("Failed to open %s", p); return PARAM_READ_ERROR; @@ -637,7 +637,7 @@ static ParameterError data_urlencode(const char *nextarg, err = file2memory(&postdata, &size, file); if(file && (file != stdin)) - fclose(file); + curlx_fclose(file); if(err) return err; } @@ -899,7 +899,7 @@ static ParameterError set_data(cmdline_t cmd, CURLX_SET_BINMODE(stdin); } else { - file = fopen(nextarg, "rb"); + file = curlx_fopen(nextarg, "rb"); if(!file) { errorf("Failed to open %s", nextarg); return PARAM_READ_ERROR; @@ -917,7 +917,7 @@ static ParameterError set_data(cmdline_t cmd, } if(file && (file != stdin)) - fclose(file); + curlx_fclose(file); if(err) return err; @@ -1094,7 +1094,7 @@ static ParameterError parse_url(struct OperationConfig *config, if(fromstdin) f = stdin; else - f = fopen(&nextarg[1], FOPEN_READTEXT); + f = curlx_fopen(&nextarg[1], FOPEN_READTEXT); if(f) { curlx_dyn_init(&line, 8092); while(my_get_line(f, &line, &error)) { @@ -1104,7 +1104,7 @@ static ParameterError parse_url(struct OperationConfig *config, break; } if(!fromstdin) - fclose(f); + curlx_fclose(f); curlx_dyn_free(&line); if(error || err) return PARAM_READ_ERROR; @@ -1206,7 +1206,7 @@ static ParameterError parse_ech(struct OperationConfig *config, file = stdin; } else { - file = fopen(nextarg, FOPEN_READTEXT); + file = curlx_fopen(nextarg, FOPEN_READTEXT); } if(!file) { warnf("Couldn't read file \"%s\" " @@ -1216,7 +1216,7 @@ static ParameterError parse_ech(struct OperationConfig *config, } err = file2string(&tmpcfg, file); if(file != stdin) - fclose(file); + curlx_fclose(file); if(err) return err; config->ech_config = aprintf("ecl:%s",tmpcfg); @@ -1242,7 +1242,7 @@ static ParameterError parse_header(struct OperationConfig *config, if(nextarg[0] == '@') { /* read many headers from a file or stdin */ bool use_stdin = !strcmp(&nextarg[1], "-"); - FILE *file = use_stdin ? stdin : fopen(&nextarg[1], FOPEN_READTEXT); + FILE *file = use_stdin ? stdin : curlx_fopen(&nextarg[1], FOPEN_READTEXT); if(!file) { errorf("Failed to open %s", &nextarg[1]); err = PARAM_READ_ERROR; @@ -1263,7 +1263,7 @@ static ParameterError parse_header(struct OperationConfig *config, err = PARAM_READ_ERROR; curlx_dyn_free(&line); if(!use_stdin) - fclose(file); + curlx_fclose(file); } } else { @@ -1536,7 +1536,7 @@ static ParameterError parse_writeout(struct OperationConfig *config, } else { fname = nextarg; - file = fopen(fname, FOPEN_READTEXT); + file = curlx_fopen(fname, FOPEN_READTEXT); if(!file) { errorf("Failed to open %s", fname); return PARAM_READ_ERROR; @@ -1545,7 +1545,7 @@ static ParameterError parse_writeout(struct OperationConfig *config, tool_safefree(config->writeout); err = file2string(&config->writeout, file); if(file && (file != stdin)) - fclose(file); + curlx_fclose(file); if(err) return err; if(!config->writeout) diff --git a/src/tool_ipfs.c b/src/tool_ipfs.c index dd030f09bc..c2f1b16523 100644 --- a/src/tool_ipfs.c +++ b/src/tool_ipfs.c @@ -88,7 +88,7 @@ static char *ipfs_gateway(void) if(!gateway_composed_file_path) goto fail; - gateway_file = fopen(gateway_composed_file_path, FOPEN_READTEXT); + gateway_file = curlx_fopen(gateway_composed_file_path, FOPEN_READTEXT); tool_safefree(gateway_composed_file_path); if(gateway_file) { @@ -103,7 +103,7 @@ static char *ipfs_gateway(void) goto fail; } - fclose(gateway_file); + curlx_fclose(gateway_file); gateway_file = NULL; if(curlx_dyn_len(&dyn)) @@ -121,7 +121,7 @@ static char *ipfs_gateway(void) } fail: if(gateway_file) - fclose(gateway_file); + curlx_fclose(gateway_file); tool_safefree(gateway); tool_safefree(ipfs_path); return NULL; diff --git a/src/tool_operate.c b/src/tool_operate.c index 14eff06e06..d5a1b26468 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -164,7 +164,7 @@ static curl_off_t vms_realfilesize(const char *name, FILE * file; /* !checksrc! disable FOPENMODE 1 */ - file = fopen(name, "r"); /* VMS */ + file = curlx_fopen(name, "r"); /* VMS */ if(!file) { return 0; } @@ -175,7 +175,7 @@ static curl_off_t vms_realfilesize(const char *name, if(ret_stat) count += ret_stat; } - fclose(file); + curlx_fclose(file); return count; } @@ -660,7 +660,7 @@ static CURLcode post_per_transfer(struct per_transfer *per, /* Close the outs file */ if(outs->fopened && outs->stream) { - rc = fclose(outs->stream); + rc = curlx_fclose(outs->stream); if(!result && rc) { /* something went wrong in the writing process */ result = CURLE_WRITE_ERROR; @@ -696,13 +696,13 @@ skip: /* Close function-local opened file descriptors */ if(per->heads.fopened && per->heads.stream) - fclose(per->heads.stream); + curlx_fclose(per->heads.stream); if(per->heads.alloc_filename) tool_safefree(per->heads.filename); if(per->etag_save.fopened && per->etag_save.stream) - fclose(per->etag_save.stream); + curlx_fclose(per->etag_save.stream); if(per->etag_save.alloc_filename) tool_safefree(per->etag_save.filename); @@ -800,7 +800,7 @@ static CURLcode etag_compare(struct OperationConfig *config) ParameterError pe; /* open file for reading: */ - FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT); + FILE *file = curlx_fopen(config->etag_compare_file, FOPEN_READTEXT); if(!file) warnf("Failed to open %s: %s", config->etag_compare_file, strerror(errno)); @@ -815,7 +815,7 @@ static CURLcode etag_compare(struct OperationConfig *config) if(!header) { if(file) - fclose(file); + curlx_fclose(file); errorf("Failed to allocate memory for custom etag header"); return CURLE_OUT_OF_MEMORY; } @@ -825,7 +825,7 @@ static CURLcode etag_compare(struct OperationConfig *config) tool_safefree(header); if(file) - fclose(file); + curlx_fclose(file); if(pe != PARAM_OK) result = CURLE_OUT_OF_MEMORY; return result; @@ -843,7 +843,7 @@ static CURLcode etag_store(struct OperationConfig *config, /* open file for output: */ if(strcmp(config->etag_save_file, "-")) { - FILE *newfile = fopen(config->etag_save_file, "ab"); + FILE *newfile = curlx_fopen(config->etag_save_file, "ab"); if(!newfile) { warnf("Failed creating file for saving etags: \"%s\". " "Skip this transfer", config->etag_save_file); @@ -893,11 +893,11 @@ static CURLcode setup_headerfile(struct OperationConfig *config, return result; } if(!per->prev || per->prev->config != config) { - newfile = fopen(config->headerfile, "wb"); + newfile = curlx_fopen(config->headerfile, "wb"); if(newfile) - fclose(newfile); + curlx_fclose(newfile); } - newfile = fopen(config->headerfile, "ab"); + newfile = curlx_fopen(config->headerfile, "ab"); if(!newfile) { errorf("Failed to open %s", config->headerfile); @@ -999,11 +999,11 @@ static CURLcode setup_outfile(struct OperationConfig *config, #ifdef __VMS /* open file for output, forcing VMS output format into stream mode which is needed for stat() call above to always work. */ - FILE *file = fopen(outfile, "ab", - "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0"); + FILE *file = curlx_fopen(outfile, "ab", + "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0"); #else /* open file for output: */ - FILE *file = fopen(per->outfile, "ab"); + FILE *file = curlx_fopen(per->outfile, "ab"); #endif if(!file) { errorf("cannot open '%s'", per->outfile); @@ -1193,7 +1193,7 @@ static CURLcode single_transfer(struct OperationConfig *config, if(result) { curl_easy_cleanup(curl); if(etag_first.fopened) - fclose(etag_first.stream); + curlx_fclose(etag_first.stream); return result; } per->etag_save = etag_first; /* copy the whole struct */ @@ -2004,7 +2004,7 @@ static CURLcode cacertpaths(struct OperationConfig *config) char *cacert = NULL; FILE *cafile = tool_execpath("curl-ca-bundle.crt", &cacert); if(cafile) { - fclose(cafile); + curlx_fclose(cafile); config->cacert = strdup(cacert); } #elif !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) && \ diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c index bc22b9d5b7..632286530a 100644 --- a/src/tool_parsecfg.c +++ b/src/tool_parsecfg.c @@ -93,7 +93,7 @@ int parseconfig(const char *filename) /* NULL means load .curlrc from homedir! */ char *curlrc = findfile(".curlrc", CURLRC_DOTSCORE); if(curlrc) { - file = fopen(curlrc, FOPEN_READTEXT); + file = curlx_fopen(curlrc, FOPEN_READTEXT); if(!file) { free(curlrc); return 1; @@ -115,7 +115,7 @@ int parseconfig(const char *filename) } else { if(strcmp(filename, "-")) - file = fopen(filename, FOPEN_READTEXT); + file = curlx_fopen(filename, FOPEN_READTEXT); else file = stdin; } @@ -250,7 +250,7 @@ int parseconfig(const char *filename) curlx_dyn_free(&buf); curlx_dyn_free(&pbuf); if(file != stdin) - fclose(file); + curlx_fclose(file); if(fileerror) rc = 1; } diff --git a/src/tool_ssls.c b/src/tool_ssls.c index edf8d6095a..6fb0180455 100644 --- a/src/tool_ssls.c +++ b/src/tool_ssls.c @@ -66,7 +66,7 @@ CURLcode tool_ssls_load(struct OperationConfig *config, bool error = FALSE; curlx_dyn_init(&buf, MAX_SSLS_LINE); - fp = fopen(filename, FOPEN_READTEXT); + fp = curlx_fopen(filename, FOPEN_READTEXT); if(!fp) { /* ok if it does not exist */ notef("SSL session file does not exist (yet?): %s", filename); goto out; @@ -122,7 +122,7 @@ out: if(easy) curl_easy_cleanup(easy); if(fp) - fclose(fp); + curlx_fclose(fp); curlx_dyn_free(&buf); curl_free(shmac); curl_free(sdata); @@ -190,7 +190,7 @@ CURLcode tool_ssls_save(struct OperationConfig *config, CURLcode r = CURLE_OK; ctx.exported = 0; - ctx.fp = fopen(filename, FOPEN_WRITETEXT); + ctx.fp = curlx_fopen(filename, FOPEN_WRITETEXT); if(!ctx.fp) { warnf("Warning: Failed to create SSL session file %s", filename); @@ -207,6 +207,6 @@ out: if(easy) curl_easy_cleanup(easy); if(ctx.fp) - fclose(ctx.fp); + curlx_fclose(ctx.fp); return r; } diff --git a/src/tool_stderr.c b/src/tool_stderr.c index b023d6c802..1116c30092 100644 --- a/src/tool_stderr.c +++ b/src/tool_stderr.c @@ -50,12 +50,12 @@ void tool_set_stderr_file(const char *filename) /* precheck that filename is accessible to lessen the chance that the subsequent freopen will fail. */ - fp = fopen(filename, FOPEN_WRITETEXT); + fp = curlx_fopen(filename, FOPEN_WRITETEXT); if(!fp) { warnf("Warning: Failed to open %s", filename); return; } - fclose(fp); + curlx_fclose(fp); /* freopen the actual stderr (stdio.h stderr) instead of tool_stderr since the latter may be set to stdout. */ diff --git a/src/tool_util.c b/src/tool_util.c index e7ab704f12..f8415d2a17 100644 --- a/src/tool_util.c +++ b/src/tool_util.c @@ -127,7 +127,7 @@ FILE *tool_execpath(const char *filename, char **pathp) if(strlen(filename) < remaining - 1) { curl_msnprintf(lastdirchar, remaining, "%s%s", DIR_CHAR, filename); *pathp = filebuffer; - return fopen(filebuffer, FOPEN_READTEXT); + return curlx_fopen(filebuffer, FOPEN_READTEXT); } } } diff --git a/src/tool_writeout.c b/src/tool_writeout.c index cdde28c909..eaeec152e4 100644 --- a/src/tool_writeout.c +++ b/src/tool_writeout.c @@ -772,13 +772,13 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per, break; case VAR_STDOUT: if(fclose_stream) - fclose(stream); + curlx_fclose(stream); fclose_stream = FALSE; stream = stdout; break; case VAR_STDERR: if(fclose_stream) - fclose(stream); + curlx_fclose(stream); fclose_stream = FALSE; stream = tool_stderr; break; @@ -824,12 +824,12 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per, FILE *stream2; memcpy(fname, ptr, flen); fname[flen] = 0; - stream2 = fopen(fname, append ? FOPEN_APPENDTEXT : - FOPEN_WRITETEXT); + stream2 = curlx_fopen(fname, append ? FOPEN_APPENDTEXT : + FOPEN_WRITETEXT); if(stream2) { /* only change if the open worked */ if(fclose_stream) - fclose(stream); + curlx_fclose(stream); stream = stream2; fclose_stream = TRUE; } @@ -872,6 +872,6 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per, } } if(fclose_stream) - fclose(stream); + curlx_fclose(stream); curlx_dyn_free(&name); } diff --git a/src/var.c b/src/var.c index 612735016c..d279fdeb6e 100644 --- a/src/var.c +++ b/src/var.c @@ -455,7 +455,7 @@ ParameterError setvariable(const char *input) if(use_stdin) file = stdin; else { - file = fopen(line, "rb"); + file = curlx_fopen(line, "rb"); if(!file) { errorf("Failed to open %s: %s", line, strerror(errno)); err = PARAM_READ_ERROR; @@ -469,7 +469,7 @@ ParameterError setvariable(const char *input) } curlx_dyn_free(&fname); if(!use_stdin && file) - fclose(file); + curlx_fclose(file); if(err) return err; } diff --git a/tests/data/test1185 b/tests/data/test1185 index 8b14f4c5ff..43a27f0870 100644 --- a/tests/data/test1185 +++ b/tests/data/test1185 @@ -47,7 +47,7 @@ func_return() ; a = sprintf(buffer, "%s", moo); -FILE *f = fopen("filename", "r"); +FILE *f = curlx_fopen("filename", "r"); void startfunc(int a, int b) { func(); @@ -124,7 +124,7 @@ void startfunc(int a, int b) { a = sprintf(buffer, "%s", moo); ^ ./%LOGDIR/code1185.c:32:11: warning: use of non-binary fopen without FOPEN_* macro: r (FOPENMODE) - FILE *f = fopen("filename", "r"); + FILE *f = curlx_fopen("filename", "r"); ^ ./%LOGDIR/code1185.c:34:30: warning: wrongly placed open brace (BRACEPOS) void startfunc(int a, int b) { diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index 00273f9e9d..c316a05269 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -34,6 +34,7 @@ UTILS_C = memptr.c testutil.c testtrace.c UTILS_H = testutil.h testtrace.h unitcheck.h CURLX_C = \ + ../../lib/curlx/fopen.c \ ../../lib/curlx/warnless.c \ ../../lib/curlx/multibyte.c \ ../../lib/curlx/timediff.c \ diff --git a/tests/libtest/cli_h2_serverpush.c b/tests/libtest/cli_h2_serverpush.c index 7b465bc61a..a865fdfd8f 100644 --- a/tests/libtest/cli_h2_serverpush.c +++ b/tests/libtest/cli_h2_serverpush.c @@ -30,7 +30,7 @@ static FILE *out_download; static int setup_h2_serverpush(CURL *hnd, const char *url) { - out_download = fopen("download_0.data", "wb"); + out_download = curlx_fopen("download_0.data", "wb"); if(!out_download) return 1; /* failed */ @@ -72,7 +72,7 @@ static int server_push_callback(CURL *parent, curl_msnprintf(filename, sizeof(filename) - 1, "push%u", count++); /* here's a new stream, save it in a new file for each new push */ - out_push = fopen(filename, "wb"); + out_push = curlx_fopen(filename, "wb"); if(!out_push) { /* if we cannot save it, deny it */ curl_mfprintf(stderr, "Failed to create output file for push\n"); @@ -129,7 +129,7 @@ static CURLcode test_cli_h2_serverpush(const char *URL) easy = curl_easy_init(); if(setup_h2_serverpush(easy, URL)) { - fclose(out_download); + curlx_fclose(out_download); curl_mfprintf(stderr, "failed\n"); return (CURLcode)1; } @@ -166,9 +166,9 @@ static CURLcode test_cli_h2_serverpush(const char *URL) curl_multi_cleanup(multi_handle); - fclose(out_download); + curlx_fclose(out_download); if(out_push) - fclose(out_push); + curlx_fclose(out_push); return CURLE_OK; } diff --git a/tests/libtest/cli_hx_download.c b/tests/libtest/cli_hx_download.c index 6394c5e25b..7a6a48c171 100644 --- a/tests/libtest/cli_hx_download.c +++ b/tests/libtest/cli_hx_download.c @@ -94,7 +94,7 @@ static size_t my_write_d_cb(char *buf, size_t nitems, size_t buflen, if(!t->out) { curl_msnprintf(t->filename, sizeof(t->filename)-1, "download_%zu.data", t->idx); - t->out = fopen(t->filename, "wb"); + t->out = curlx_fopen(t->filename, "wb"); if(!t->out) return 0; } @@ -530,7 +530,7 @@ static CURLcode test_cli_hx_download(const char *URL) for(i = 0; i < transfer_count_d; ++i) { t = &transfer_d[i]; if(t->out) { - fclose(t->out); + curlx_fclose(t->out); t->out = NULL; } if(t->easy) { diff --git a/tests/libtest/cli_hx_upload.c b/tests/libtest/cli_hx_upload.c index 9c69e36787..40e486c41a 100644 --- a/tests/libtest/cli_hx_upload.c +++ b/tests/libtest/cli_hx_upload.c @@ -74,7 +74,7 @@ static size_t my_write_u_cb(char *buf, size_t nitems, size_t buflen, if(!t->out) { curl_msnprintf(t->filename, sizeof(t->filename)-1, "download_%zu.data", t->idx); - t->out = fopen(t->filename, "wb"); + t->out = curlx_fopen(t->filename, "wb"); if(!t->out) return 0; } @@ -494,7 +494,7 @@ static CURLcode test_cli_hx_upload(const char *URL) for(i = 0; i < transfer_count_u; ++i) { t = &transfer_u[i]; if(t->out) { - fclose(t->out); + curlx_fclose(t->out); t->out = NULL; } if(t->easy) { diff --git a/tests/libtest/lib500.c b/tests/libtest/lib500.c index 7081ec625d..ffb974f4f0 100644 --- a/tests/libtest/lib500.c +++ b/tests/libtest/lib500.c @@ -90,7 +90,7 @@ static CURLcode test_lib500(const char *URL) if(!res) { res = curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ipstr); if(libtest_arg2) { - FILE *moo = fopen(libtest_arg2, "wb"); + FILE *moo = curlx_fopen(libtest_arg2, "wb"); if(moo) { curl_off_t time_namelookup; curl_off_t time_connect; @@ -163,7 +163,7 @@ static CURLcode test_lib500(const char *URL) (long)(time_total % 1000000)); } - fclose(moo); + curlx_fclose(moo); } } } diff --git a/tests/libtest/lib505.c b/tests/libtest/lib505.c index 2285208e9f..fc20094584 100644 --- a/tests/libtest/lib505.c +++ b/tests/libtest/lib505.c @@ -51,7 +51,7 @@ static CURLcode test_lib505(const char *URL) return TEST_ERR_USAGE; } - hd_src = fopen(libtest_arg2, "rb"); + hd_src = curlx_fopen(libtest_arg2, "rb"); if(!hd_src) { curl_mfprintf(stderr, "fopen failed with error (%d) %s\n", errno, strerror(errno)); @@ -70,19 +70,19 @@ static CURLcode test_lib505(const char *URL) curl_mfprintf(stderr, "fstat() failed with error (%d) %s\n", errno, strerror(errno)); curl_mfprintf(stderr, "Error opening file '%s'\n", libtest_arg2); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } if(!file_info.st_size) { curl_mfprintf(stderr, "File %s has zero size!\n", libtest_arg2); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { curl_mfprintf(stderr, "curl_global_init() failed\n"); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } @@ -91,7 +91,7 @@ static CURLcode test_lib505(const char *URL) if(!curl) { curl_mfprintf(stderr, "curl_easy_init() failed\n"); curl_global_cleanup(); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } @@ -102,7 +102,7 @@ static CURLcode test_lib505(const char *URL) curl_mfprintf(stderr, "curl_slist_append() failed\n"); curl_easy_cleanup(curl); curl_global_cleanup(); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } headerlist = curl_slist_append(hl, buf_2); @@ -111,7 +111,7 @@ static CURLcode test_lib505(const char *URL) curl_slist_free_all(hl); curl_easy_cleanup(curl); curl_global_cleanup(); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } headerlist = hl; @@ -144,7 +144,7 @@ test_cleanup: curl_slist_free_all(headerlist); /* close the local file */ - fclose(hd_src); + curlx_fclose(hd_src); curl_easy_cleanup(curl); curl_global_cleanup(); diff --git a/tests/libtest/lib518.c b/tests/libtest/lib518.c index 86eddec003..9cf3a42554 100644 --- a/tests/libtest/lib518.c +++ b/tests/libtest/lib518.c @@ -77,7 +77,7 @@ static int t518_fopen_works(void) fpa[i] = NULL; } for(i = 0; i < 3; i++) { - fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT); + fpa[i] = curlx_fopen(DEV_NULL, FOPEN_READTEXT); if(!fpa[i]) { t518_store_errmsg("fopen failed", errno); curl_mfprintf(stderr, "%s\n", t518_msgbuff); @@ -87,7 +87,7 @@ static int t518_fopen_works(void) } for(i = 0; i < 3; i++) { if(fpa[i]) - fclose(fpa[i]); + curlx_fclose(fpa[i]); } return ret; } diff --git a/tests/libtest/lib525.c b/tests/libtest/lib525.c index 6c7d650366..007889fdc7 100644 --- a/tests/libtest/lib525.c +++ b/tests/libtest/lib525.c @@ -42,7 +42,7 @@ static CURLcode test_lib525(const char *URL) return TEST_ERR_USAGE; } - hd_src = fopen(libtest_arg2, "rb"); + hd_src = curlx_fopen(libtest_arg2, "rb"); if(!hd_src) { curl_mfprintf(stderr, "fopen failed with error (%d) %s\n", errno, strerror(errno)); @@ -61,13 +61,13 @@ static CURLcode test_lib525(const char *URL) curl_mfprintf(stderr, "fstat() failed with error (%d) %s\n", errno, strerror(errno)); curl_mfprintf(stderr, "Error opening file '%s'\n", libtest_arg2); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_FSTAT; } res_global_init(CURL_GLOBAL_ALL); if(res) { - fclose(hd_src); + curlx_fclose(hd_src); return res; } @@ -149,7 +149,7 @@ test_cleanup: } /* close the local file */ - fclose(hd_src); + curlx_fclose(hd_src); return res; } diff --git a/tests/libtest/lib537.c b/tests/libtest/lib537.c index fa03c3b983..90de8a2d0c 100644 --- a/tests/libtest/lib537.c +++ b/tests/libtest/lib537.c @@ -74,7 +74,7 @@ static int t537_fopen_works(void) fpa[i] = NULL; } for(i = 0; i < 3; i++) { - fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT); + fpa[i] = curlx_fopen(DEV_NULL, FOPEN_READTEXT); if(!fpa[i]) { t537_store_errmsg("fopen failed", errno); curl_mfprintf(stderr, "%s\n", t537_msgbuff); @@ -84,7 +84,7 @@ static int t537_fopen_works(void) } for(i = 0; i < 3; i++) { if(fpa[i]) - fclose(fpa[i]); + curlx_fclose(fpa[i]); } return ret; } diff --git a/tests/libtest/lib541.c b/tests/libtest/lib541.c index 9868474d01..3bb64f8ac4 100644 --- a/tests/libtest/lib541.c +++ b/tests/libtest/lib541.c @@ -42,7 +42,7 @@ static CURLcode test_lib541(const char *URL) return TEST_ERR_USAGE; } - hd_src = fopen(libtest_arg2, "rb"); + hd_src = curlx_fopen(libtest_arg2, "rb"); if(!hd_src) { curl_mfprintf(stderr, "fopen failed with error (%d) %s\n", errno, strerror(errno)); @@ -61,19 +61,19 @@ static CURLcode test_lib541(const char *URL) curl_mfprintf(stderr, "fstat() failed with error (%d) %s\n", errno, strerror(errno)); curl_mfprintf(stderr, "Error opening file '%s'\n", libtest_arg2); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } if(!file_info.st_size) { curl_mfprintf(stderr, "File %s has zero size!\n", libtest_arg2); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { curl_mfprintf(stderr, "curl_global_init() failed\n"); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } @@ -82,7 +82,7 @@ static CURLcode test_lib541(const char *URL) if(!curl) { curl_mfprintf(stderr, "curl_easy_init() failed\n"); curl_global_cleanup(); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_MAJOR_BAD; } @@ -110,7 +110,7 @@ static CURLcode test_lib541(const char *URL) test_cleanup: /* close the local file */ - fclose(hd_src); + curlx_fclose(hd_src); curl_easy_cleanup(curl); curl_global_cleanup(); diff --git a/tests/libtest/lib566.c b/tests/libtest/lib566.c index 15221cd0cc..79f48f235b 100644 --- a/tests/libtest/lib566.c +++ b/tests/libtest/lib566.c @@ -54,10 +54,10 @@ static CURLcode test_lib566(const char *URL) res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length); - moo = fopen(libtest_arg2, "wb"); + moo = curlx_fopen(libtest_arg2, "wb"); if(moo) { curl_mfprintf(moo, "CL %.0f\n", content_length); - fclose(moo); + curlx_fclose(moo); } } diff --git a/tests/libtest/lib568.c b/tests/libtest/lib568.c index 8e34194ef5..83c6fd2394 100644 --- a/tests/libtest/lib568.c +++ b/tests/libtest/lib568.c @@ -75,7 +75,7 @@ static CURLcode test_lib568(const char *URL) fstat(sdp, &file_info); close(sdp); - sdpf = fopen(libtest_arg2, "rb"); + sdpf = curlx_fopen(libtest_arg2, "rb"); if(!sdpf) { curl_mfprintf(stderr, "can't fopen %s\n", libtest_arg2); res = TEST_ERR_MAJOR_BAD; @@ -94,7 +94,7 @@ static CURLcode test_lib568(const char *URL) goto test_cleanup; test_setopt(curl, CURLOPT_UPLOAD, 0L); - fclose(sdpf); + curlx_fclose(sdpf); sdpf = NULL; /* Make sure we can do a normal request now */ @@ -159,7 +159,7 @@ static CURLcode test_lib568(const char *URL) test_cleanup: if(sdpf) - fclose(sdpf); + curlx_fclose(sdpf); curl_free(stream_uri); diff --git a/tests/libtest/lib569.c b/tests/libtest/lib569.c index 8f340b489d..b1a80a7b01 100644 --- a/tests/libtest/lib569.c +++ b/tests/libtest/lib569.c @@ -38,7 +38,7 @@ static CURLcode test_lib569(const char *URL) int request = 1; int i; - FILE *idfile = fopen(libtest_arg2, "wb"); + FILE *idfile = curlx_fopen(libtest_arg2, "wb"); if(!idfile) { curl_mfprintf(stderr, "couldn't open the Session ID File\n"); return TEST_ERR_MAJOR_BAD; @@ -46,7 +46,7 @@ static CURLcode test_lib569(const char *URL) if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { curl_mfprintf(stderr, "curl_global_init() failed\n"); - fclose(idfile); + curlx_fclose(idfile); return TEST_ERR_MAJOR_BAD; } @@ -54,7 +54,7 @@ static CURLcode test_lib569(const char *URL) if(!curl) { curl_mfprintf(stderr, "curl_easy_init() failed\n"); curl_global_cleanup(); - fclose(idfile); + curlx_fclose(idfile); return TEST_ERR_MAJOR_BAD; } @@ -116,7 +116,7 @@ static CURLcode test_lib569(const char *URL) test_cleanup: if(idfile) - fclose(idfile); + curlx_fclose(idfile); curl_free(stream_uri); curl_easy_cleanup(curl); diff --git a/tests/libtest/lib571.c b/tests/libtest/lib571.c index 2cf4128e7a..49afc2211d 100644 --- a/tests/libtest/lib571.c +++ b/tests/libtest/lib571.c @@ -95,7 +95,7 @@ static CURLcode test_lib571(const char *URL) char *stream_uri = NULL; int request = 1; - FILE *protofile = fopen(libtest_arg2, "wb"); + FILE *protofile = curlx_fopen(libtest_arg2, "wb"); if(!protofile) { curl_mfprintf(stderr, "Couldn't open the protocol dump file\n"); return TEST_ERR_MAJOR_BAD; @@ -103,14 +103,14 @@ static CURLcode test_lib571(const char *URL) if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { curl_mfprintf(stderr, "curl_global_init() failed\n"); - fclose(protofile); + curlx_fclose(protofile); return TEST_ERR_MAJOR_BAD; } curl = curl_easy_init(); if(!curl) { curl_mfprintf(stderr, "curl_easy_init() failed\n"); - fclose(protofile); + curlx_fclose(protofile); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } @@ -194,7 +194,7 @@ test_cleanup: curl_free(stream_uri); if(protofile) - fclose(protofile); + curlx_fclose(protofile); curl_easy_cleanup(curl); curl_global_cleanup(); diff --git a/tests/libtest/lib572.c b/tests/libtest/lib572.c index ea9e34e068..ef5e066023 100644 --- a/tests/libtest/lib572.c +++ b/tests/libtest/lib572.c @@ -93,7 +93,7 @@ static CURLcode test_lib572(const char *URL) fstat(params, &file_info); close(params); - paramsf = fopen(libtest_arg2, "rb"); + paramsf = curlx_fopen(libtest_arg2, "rb"); if(!paramsf) { curl_mfprintf(stderr, "can't fopen %s\n", libtest_arg2); res = TEST_ERR_MAJOR_BAD; @@ -110,7 +110,7 @@ static CURLcode test_lib572(const char *URL) goto test_cleanup; test_setopt(curl, CURLOPT_UPLOAD, 0L); - fclose(paramsf); + curlx_fclose(paramsf); paramsf = NULL; /* Heartbeat GET_PARAMETERS */ @@ -163,7 +163,7 @@ static CURLcode test_lib572(const char *URL) test_cleanup: if(paramsf) - fclose(paramsf); + curlx_fclose(paramsf); curl_free(stream_uri); diff --git a/tests/libtest/lib578.c b/tests/libtest/lib578.c index a15c9a4f81..b6be1600f4 100644 --- a/tests/libtest/lib578.c +++ b/tests/libtest/lib578.c @@ -33,7 +33,7 @@ static size_t data_size = CURL_ARRAYSIZE(t578_testdata); static int t578_progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { - FILE *moo = fopen(libtest_arg2, "wb"); + FILE *moo = curlx_fopen(libtest_arg2, "wb"); (void)clientp; (void)dltotal; @@ -45,7 +45,7 @@ static int t578_progress_callback(void *clientp, double dltotal, double dlnow, else curl_mfprintf(moo, "Progress callback called with UL %f out of %f\n", ulnow, ultotal); - fclose(moo); + curlx_fclose(moo); } return 0; } diff --git a/tests/libtest/lib579.c b/tests/libtest/lib579.c index 76ecefe4ec..29396941cc 100644 --- a/tests/libtest/lib579.c +++ b/tests/libtest/lib579.c @@ -35,11 +35,11 @@ static size_t last_ul_total = 0; static void progress_final_report(void) { - FILE *moo = fopen(libtest_arg2, "ab"); + FILE *moo = curlx_fopen(libtest_arg2, "ab"); curl_mfprintf(moo ? moo : stderr, "Progress: end UL %zu/%zu\n", last_ul, last_ul_total); if(moo) - fclose(moo); + curlx_fclose(moo); else curl_mfprintf(stderr, "Progress: end UL, can't open %s\n", libtest_arg2); started = FALSE; @@ -59,11 +59,11 @@ static int t579_progress_callback(void *clientp, double dltotal, double dlnow, last_ul = (size_t)ulnow; last_ul_total = (size_t)ultotal; if(!started) { - FILE *moo = fopen(libtest_arg2, "ab"); + FILE *moo = curlx_fopen(libtest_arg2, "ab"); curl_mfprintf(moo ? moo : stderr, "Progress: start UL %zu/%zu\n", last_ul, last_ul_total); if(moo) - fclose(moo); + curlx_fclose(moo); else curl_mfprintf(stderr, "Progress: start UL, can't open %s\n", libtest_arg2); diff --git a/tests/libtest/lib582.c b/tests/libtest/lib582.c index 70a9ab65dc..b197063221 100644 --- a/tests/libtest/lib582.c +++ b/tests/libtest/lib582.c @@ -243,7 +243,7 @@ static CURLcode test_lib582(const char *URL) return TEST_ERR_USAGE; } - hd_src = fopen(libtest_arg2, "rb"); + hd_src = curlx_fopen(libtest_arg2, "rb"); if(!hd_src) { curl_mfprintf(stderr, "fopen() failed with error (%d) %s\n", errno, strerror(errno)); @@ -262,7 +262,7 @@ static CURLcode test_lib582(const char *URL) curl_mfprintf(stderr, "fstat() failed with error (%d) %s\n", errno, strerror(errno)); curl_mfprintf(stderr, "Error opening file '%s'\n", libtest_arg2); - fclose(hd_src); + curlx_fclose(hd_src); return TEST_ERR_FSTAT; } curl_mfprintf(stderr, "Set to upload %" CURL_FORMAT_CURL_OFF_T " bytes\n", @@ -270,7 +270,7 @@ static CURLcode test_lib582(const char *URL) res_global_init(CURL_GLOBAL_ALL); if(res != CURLE_OK) { - fclose(hd_src); + curlx_fclose(hd_src); return res; } @@ -356,7 +356,7 @@ test_cleanup: curl_global_cleanup(); /* close the local file */ - fclose(hd_src); + curlx_fclose(hd_src); /* free local memory */ free(sockets.read.sockets); diff --git a/tests/libtest/lib591.c b/tests/libtest/lib591.c index 1f09fbdc4d..77a038c7c3 100644 --- a/tests/libtest/lib591.c +++ b/tests/libtest/lib591.c @@ -39,7 +39,7 @@ static CURLcode test_lib591(const char *URL) start_test_timing(); - upload = fopen(libtest_arg3, "rb"); + upload = curlx_fopen(libtest_arg3, "rb"); if(!upload) { curl_mfprintf(stderr, "fopen() failed with error (%d) %s\n", errno, strerror(errno)); @@ -49,7 +49,7 @@ static CURLcode test_lib591(const char *URL) res_global_init(CURL_GLOBAL_ALL); if(res) { - fclose(upload); + curlx_fclose(upload); return res; } @@ -138,7 +138,7 @@ test_cleanup: curl_global_cleanup(); /* close the local file */ - fclose(upload); + curlx_fclose(upload); return res; } diff --git a/tests/libtest/lib599.c b/tests/libtest/lib599.c index 5b52698a29..199ef90dbf 100644 --- a/tests/libtest/lib599.c +++ b/tests/libtest/lib599.c @@ -82,10 +82,10 @@ static CURLcode test_lib599(const char *URL) FILE *moo; res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length); - moo = fopen(libtest_arg2, "wb"); + moo = curlx_fopen(libtest_arg2, "wb"); if(moo) { curl_mfprintf(moo, "CL %.0f\n", content_length); - fclose(moo); + curlx_fclose(moo); } } diff --git a/tests/libtest/lib678.c b/tests/libtest/lib678.c index 78e03c004f..5fdabdda96 100644 --- a/tests/libtest/lib678.c +++ b/tests/libtest/lib678.c @@ -30,7 +30,7 @@ static int loadfile(const char *filename, void **filedata, size_t *filesize) size_t datasize = 0; void *data = NULL; if(filename) { - FILE *fInCert = fopen(filename, "rb"); + FILE *fInCert = curlx_fopen(filename, "rb"); if(fInCert) { long cert_tell = 0; @@ -48,7 +48,7 @@ static int loadfile(const char *filename, void **filedata, size_t *filesize) if((!data) || ((int)fread(data, datasize, 1, fInCert) != 1)) continue_reading = FALSE; - fclose(fInCert); + curlx_fclose(fInCert); if(!continue_reading) { free(data); datasize = 0; diff --git a/tests/server/.checksrc b/tests/server/.checksrc index be8f12cec0..670d4b8009 100644 --- a/tests/server/.checksrc +++ b/tests/server/.checksrc @@ -1,4 +1,6 @@ allowfunc accept +allowfunc fclose +allowfunc fopen allowfunc freeaddrinfo allowfunc getaddrinfo allowfunc recv diff --git a/tests/server/Makefile.inc b/tests/server/Makefile.inc index 2e3791c774..be35fe7c4f 100644 --- a/tests/server/Makefile.inc +++ b/tests/server/Makefile.inc @@ -35,6 +35,7 @@ UTILS_H = CURLX_C = \ ../../lib/curlx/base64.c \ + ../../lib/curlx/fopen.c \ ../../lib/curlx/inet_pton.c \ ../../lib/curlx/inet_ntop.c \ ../../lib/curlx/multibyte.c \ diff --git a/tests/unit/unit3200.c b/tests/unit/unit3200.c index 023bf0ddb6..5c3e4d14ad 100644 --- a/tests/unit/unit3200.c +++ b/tests/unit/unit3200.c @@ -84,12 +84,12 @@ static CURLcode test_unit3200(const char *arg) char *line; curlx_dyn_init(&buf, len); - fp = fopen(arg, "wb"); + fp = curlx_fopen(arg, "wb"); abort_unless(fp != NULL, "Cannot open testfile"); fwrite(filecontents[i], 1, strlen(filecontents[i]), fp); - fclose(fp); + curlx_fclose(fp); - fp = fopen(arg, "rb"); + fp = curlx_fopen(arg, "rb"); abort_unless(fp != NULL, "Cannot open testfile"); curl_mfprintf(stderr, "Test %zd...", i); @@ -158,7 +158,7 @@ static CURLcode test_unit3200(const char *arg) break; } curlx_dyn_free(&buf); - fclose(fp); + curlx_fclose(fp); curl_mfprintf(stderr, "OK\n"); } return (CURLcode)rc; -- 2.47.3