summaryrefslogtreecommitdiff
path: root/Utilities
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:13:24 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:13:24 +0900
commite42c4abb646a39cdd5d1ccb22a9619990ce2a898 (patch)
tree5c4a99e76409f26c9525137e845d0bac7efa8c7b /Utilities
parent07408dd83a3637a29a56a7d5fbe49f63cbb41e8f (diff)
downloadcmake-e42c4abb646a39cdd5d1ccb22a9619990ce2a898.tar.gz
cmake-e42c4abb646a39cdd5d1ccb22a9619990ce2a898.tar.bz2
cmake-e42c4abb646a39cdd5d1ccb22a9619990ce2a898.zip
Imported Upstream version 3.12.0upstream/3.12.0
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/Release/linux64_release.cmake8
-rw-r--r--Utilities/Release/upload_release.cmake2
-rw-r--r--Utilities/Release/win32_release.cmake2
-rw-r--r--Utilities/Release/win64_release.cmake2
-rwxr-xr-xUtilities/Scripts/clang-format.bash11
-rwxr-xr-xUtilities/Scripts/regenerate-lexers.bash39
-rwxr-xr-xUtilities/Scripts/regenerate-parsers.bash37
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rw-r--r--Utilities/Sphinx/CMakeLists.txt29
-rw-r--r--Utilities/Sphinx/cmake.py6
-rw-r--r--Utilities/Sphinx/conf.py.in1
-rwxr-xr-xUtilities/Sphinx/create_identifiers.py2
-rw-r--r--Utilities/Sphinx/static/cmake.css10
-rw-r--r--Utilities/cm_bzlib.h4
-rw-r--r--Utilities/cm_curl.h4
-rw-r--r--Utilities/cm_expat.h4
-rw-r--r--Utilities/cm_jsoncpp_reader.h4
-rw-r--r--Utilities/cm_jsoncpp_value.h4
-rw-r--r--Utilities/cm_jsoncpp_writer.h4
-rw-r--r--Utilities/cm_kwiml.h8
-rw-r--r--Utilities/cm_libarchive.h8
-rw-r--r--Utilities/cm_lzma.h4
-rw-r--r--Utilities/cm_rhash.h4
-rw-r--r--Utilities/cm_uv.h4
-rw-r--r--Utilities/cm_xmlrpc.h4
-rw-r--r--Utilities/cm_zlib.h4
-rw-r--r--Utilities/cmcurl/CMake/FindBrotli.cmake20
-rw-r--r--Utilities/cmcurl/CMakeLists.txt34
-rw-r--r--Utilities/cmcurl/include/curl/curl.h35
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h10
-rw-r--r--Utilities/cmcurl/include/curl/multi.h6
-rw-r--r--Utilities/cmcurl/include/curl/system.h4
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h13
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc12
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c67
-rw-r--r--Utilities/cmcurl/lib/connect.c35
-rw-r--r--Utilities/cmcurl/lib/connect.h7
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c5
-rw-r--r--Utilities/cmcurl/lib/cookie.c276
-rw-r--r--Utilities/cmcurl/lib/cookie.h8
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c10
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake3
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.c133
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.h81
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.c327
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c7
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.c19
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c15
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c2
-rw-r--r--Utilities/cmcurl/lib/curl_path.h5
-rw-r--r--Utilities/cmcurl/lib/curl_range.c95
-rw-r--r--Utilities/cmcurl/lib/curl_range.h30
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c34
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h46
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h23
-rw-r--r--Utilities/cmcurl/lib/easy.c32
-rw-r--r--Utilities/cmcurl/lib/file.c70
-rw-r--r--Utilities/cmcurl/lib/fileinfo.c7
-rw-r--r--Utilities/cmcurl/lib/fileinfo.h5
-rw-r--r--Utilities/cmcurl/lib/formdata.c64
-rw-r--r--Utilities/cmcurl/lib/ftp.c183
-rw-r--r--Utilities/cmcurl/lib/ftp.h4
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c31
-rw-r--r--Utilities/cmcurl/lib/getinfo.c12
-rw-r--r--Utilities/cmcurl/lib/hash.c6
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c2
-rw-r--r--Utilities/cmcurl/lib/hostip.c202
-rw-r--r--Utilities/cmcurl/lib/hostip.h13
-rw-r--r--Utilities/cmcurl/lib/http.c223
-rw-r--r--Utilities/cmcurl/lib/http.h15
-rw-r--r--Utilities/cmcurl/lib/http2.c279
-rw-r--r--Utilities/cmcurl/lib/http_chunks.c30
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c2
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c14
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c12
-rw-r--r--Utilities/cmcurl/lib/krb5.c6
-rw-r--r--Utilities/cmcurl/lib/md5.c7
-rw-r--r--Utilities/cmcurl/lib/mime.c22
-rw-r--r--Utilities/cmcurl/lib/mime.h5
-rw-r--r--Utilities/cmcurl/lib/multi.c166
-rw-r--r--Utilities/cmcurl/lib/multihandle.h1
-rw-r--r--Utilities/cmcurl/lib/multiif.h7
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c16
-rw-r--r--Utilities/cmcurl/lib/nwlib.c4
-rw-r--r--Utilities/cmcurl/lib/openldap.c66
-rw-r--r--Utilities/cmcurl/lib/parsedate.c101
-rw-r--r--Utilities/cmcurl/lib/pingpong.c5
-rw-r--r--Utilities/cmcurl/lib/progress.c113
-rw-r--r--Utilities/cmcurl/lib/progress.h13
-rw-r--r--Utilities/cmcurl/lib/rtsp.c33
-rw-r--r--Utilities/cmcurl/lib/sendf.c65
-rw-r--r--Utilities/cmcurl/lib/sendf.h4
-rw-r--r--Utilities/cmcurl/lib/setopt.c69
-rw-r--r--Utilities/cmcurl/lib/sha256.c12
-rw-r--r--Utilities/cmcurl/lib/smb.c29
-rw-r--r--Utilities/cmcurl/lib/smtp.c5
-rw-r--r--Utilities/cmcurl/lib/ssh-libssh.c11
-rw-r--r--Utilities/cmcurl/lib/ssh.c101
-rw-r--r--Utilities/cmcurl/lib/strerror.c6
-rw-r--r--Utilities/cmcurl/lib/strtoofft.c2
-rw-r--r--Utilities/cmcurl/lib/telnet.c6
-rw-r--r--Utilities/cmcurl/lib/tftp.c4
-rw-r--r--Utilities/cmcurl/lib/timeval.c4
-rw-r--r--Utilities/cmcurl/lib/transfer.c75
-rw-r--r--Utilities/cmcurl/lib/transfer.h3
-rw-r--r--Utilities/cmcurl/lib/url.c106
-rw-r--r--Utilities/cmcurl/lib/urldata.h55
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c14
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c10
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c12
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.h8
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c20
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c10
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.c6
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h2
-rw-r--r--Utilities/cmcurl/lib/version.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c31
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c90
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c31
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c21
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c27
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c227
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c16
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c483
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h40
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c551
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c25
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h21
-rw-r--r--Utilities/cmcurl/lib/warnless.h2
-rw-r--r--Utilities/cmcurl/lib/wildcard.c20
-rw-r--r--Utilities/cmcurl/lib/wildcard.h8
-rw-r--r--Utilities/cmlibuv/include/uv-errno.h132
-rw-r--r--Utilities/cmlibuv/include/uv-os390.h2
-rw-r--r--Utilities/cmlibuv/include/uv-unix.h2
-rw-r--r--Utilities/cmlibuv/include/uv-version.h4
-rw-r--r--Utilities/cmlibuv/include/uv.h35
-rw-r--r--Utilities/cmlibuv/src/unix/aix-common.c26
-rw-r--r--Utilities/cmlibuv/src/unix/aix.c46
-rw-r--r--Utilities/cmlibuv/src/unix/async.c8
-rw-r--r--Utilities/cmlibuv/src/unix/bsd-ifaddrs.c4
-rw-r--r--Utilities/cmlibuv/src/unix/core.c137
-rw-r--r--Utilities/cmlibuv/src/unix/cygwin.c2
-rw-r--r--Utilities/cmlibuv/src/unix/darwin-proctitle.c13
-rw-r--r--Utilities/cmlibuv/src/unix/darwin.c24
-rw-r--r--Utilities/cmlibuv/src/unix/freebsd.c34
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c105
-rw-r--r--Utilities/cmlibuv/src/unix/fsevents.c26
-rw-r--r--Utilities/cmlibuv/src/unix/getaddrinfo.c10
-rw-r--r--Utilities/cmlibuv/src/unix/getnameinfo.c2
-rw-r--r--Utilities/cmlibuv/src/unix/ibmi.c2
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h17
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c8
-rw-r--r--Utilities/cmlibuv/src/unix/linux-core.c34
-rw-r--r--Utilities/cmlibuv/src/unix/linux-inotify.c10
-rw-r--r--Utilities/cmlibuv/src/unix/loop-watcher.c2
-rw-r--r--Utilities/cmlibuv/src/unix/loop.c3
-rw-r--r--Utilities/cmlibuv/src/unix/netbsd.c28
-rw-r--r--Utilities/cmlibuv/src/unix/no-fsevents.c6
-rw-r--r--Utilities/cmlibuv/src/unix/no-proctitle.c2
-rw-r--r--Utilities/cmlibuv/src/unix/openbsd.c32
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.c2
-rw-r--r--Utilities/cmlibuv/src/unix/os390.c38
-rw-r--r--Utilities/cmlibuv/src/unix/pipe.c63
-rw-r--r--Utilities/cmlibuv/src/unix/poll.c4
-rw-r--r--Utilities/cmlibuv/src/unix/posix-poll.c18
-rw-r--r--Utilities/cmlibuv/src/unix/process.c112
-rw-r--r--Utilities/cmlibuv/src/unix/procfs-exepath.c4
-rw-r--r--Utilities/cmlibuv/src/unix/proctitle.c4
-rw-r--r--Utilities/cmlibuv/src/unix/signal.c4
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c90
-rw-r--r--Utilities/cmlibuv/src/unix/sunos.c42
-rw-r--r--Utilities/cmlibuv/src/unix/tcp.c66
-rw-r--r--Utilities/cmlibuv/src/unix/thread.c256
-rw-r--r--Utilities/cmlibuv/src/unix/timer.c4
-rw-r--r--Utilities/cmlibuv/src/unix/tty.c16
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c76
-rw-r--r--Utilities/cmlibuv/src/uv-common.c2
-rw-r--r--Utilities/cmlibuv/src/uv-common.h12
-rw-r--r--Utilities/cmlibuv/src/win/core.c10
-rw-r--r--Utilities/cmlibuv/src/win/fs-event.c29
-rw-r--r--Utilities/cmlibuv/src/win/fs.c15
-rw-r--r--Utilities/cmlibuv/src/win/getaddrinfo.c10
-rw-r--r--Utilities/cmlibuv/src/win/internal.h10
-rw-r--r--Utilities/cmlibuv/src/win/pipe.c8
-rw-r--r--Utilities/cmlibuv/src/win/process.c67
-rw-r--r--Utilities/cmlibuv/src/win/stream-inl.h10
-rw-r--r--Utilities/cmlibuv/src/win/tcp.c15
-rw-r--r--Utilities/cmlibuv/src/win/tty.c10
-rw-r--r--Utilities/cmlibuv/src/win/util.c99
-rw-r--r--Utilities/cmlibuv/src/win/winapi.c11
-rw-r--r--Utilities/cmlibuv/src/win/winapi.h15
-rw-r--r--Utilities/cmlibuv/src/win/winsock.c6
194 files changed, 4919 insertions, 2565 deletions
diff --git a/Utilities/Release/linux64_release.cmake b/Utilities/Release/linux64_release.cmake
index 97fc33c99..04a74ac80 100644
--- a/Utilities/Release/linux64_release.cmake
+++ b/Utilities/Release/linux64_release.cmake
@@ -29,12 +29,12 @@ CURSES_LIBRARY:FILEPATH=/home/kitware/ncurses-5.9/lib/libncurses.a
CURSES_INCLUDE_PATH:PATH=/home/kitware/ncurses-5.9/include
FORM_LIBRARY:FILEPATH=/home/kitware/ncurses-5.9/lib/libform.a
CMAKE_USE_OPENSSL:BOOL=ON
-OPENSSL_CRYPTO_LIBRARY:STRING=/home/kitware/openssl-1.1.0g/lib/libcrypto.a;-pthread
-OPENSSL_INCLUDE_DIR:PATH=/home/kitware/openssl-1.1.0g/include
-OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.1.0g/lib/libssl.a
+OPENSSL_CRYPTO_LIBRARY:STRING=/home/kitware/openssl-1.1.0h/lib/libcrypto.a;-pthread
+OPENSSL_INCLUDE_DIR:PATH=/home/kitware/openssl-1.1.0h/include
+OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.1.0h/lib/libssl.a
PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3
CPACK_SYSTEM_NAME:STRING=Linux-x86_64
-BUILD_QtDialog:BOOL:=TRUE
+BUILD_QtDialog:BOOL=TRUE
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMAKE_PREFIX_PATH:STRING=${qt_prefix}
diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake
index f627966a9..1edcd65b1 100644
--- a/Utilities/Release/upload_release.cmake
+++ b/Utilities/Release/upload_release.cmake
@@ -1,6 +1,6 @@
set(CTEST_RUN_CURRENT_SCRIPT 0)
if(NOT VERSION)
- set(VERSION 3.11)
+ set(VERSION 3.12)
endif()
if(NOT DEFINED PROJECT_PREFIX)
set(PROJECT_PREFIX cmake-${VERSION})
diff --git a/Utilities/Release/win32_release.cmake b/Utilities/Release/win32_release.cmake
index bdf002e8e..f9e35a543 100644
--- a/Utilities/Release/win32_release.cmake
+++ b/Utilities/Release/win32_release.cmake
@@ -21,7 +21,7 @@ CMAKE_USE_OPENSSL:BOOL=OFF
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMAKE_Fortran_COMPILER:FILEPATH=FALSE
CMAKE_GENERATOR:INTERNAL=Ninja
-BUILD_QtDialog:BOOL:=TRUE
+BUILD_QtDialog:BOOL=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
diff --git a/Utilities/Release/win64_release.cmake b/Utilities/Release/win64_release.cmake
index 1c81f82c7..02e409652 100644
--- a/Utilities/Release/win64_release.cmake
+++ b/Utilities/Release/win64_release.cmake
@@ -21,7 +21,7 @@ CMAKE_USE_OPENSSL:BOOL=OFF
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMAKE_Fortran_COMPILER:FILEPATH=FALSE
CMAKE_GENERATOR:INTERNAL=Ninja
-BUILD_QtDialog:BOOL:=TRUE
+BUILD_QtDialog:BOOL=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash
index 3b331a18f..7ca4433a8 100755
--- a/Utilities/Scripts/clang-format.bash
+++ b/Utilities/Scripts/clang-format.bash
@@ -78,8 +78,8 @@ test "$#" = 0 || die "$usage"
# Find a default tool.
tools='
+ clang-format-6.0
clang-format
- clang-format-3.8
'
if test "x$clang_format" = "x"; then
for tool in $tools; do
@@ -96,6 +96,11 @@ if ! type -p "$clang_format" >/dev/null; then
exit 1
fi
+if ! "$clang_format" --version | grep 'clang-format version 6\.0' >/dev/null 2>/dev/null; then
+ echo "clang-format version 6.0 is required (exactly)"
+ exit 1
+fi
+
# Select listing mode.
case "$mode" in
'') echo "$usage"; exit 0 ;;
@@ -110,8 +115,8 @@ esac
$git_ls |
# Select sources with our attribute.
- git check-attr --stdin format.clang-format |
- grep -e ': format\.clang-format: set$' |
+ git check-attr --stdin format.clang-format-6.0 |
+ grep -e ': format\.clang-format-6\.0: set$' |
sed -n 's/:[^:]*:[^:]*$//p' |
# Update sources in-place.
diff --git a/Utilities/Scripts/regenerate-lexers.bash b/Utilities/Scripts/regenerate-lexers.bash
index 22b681faa..b09f25bf1 100755
--- a/Utilities/Scripts/regenerate-lexers.bash
+++ b/Utilities/Scripts/regenerate-lexers.bash
@@ -2,6 +2,11 @@
set -e
+forced=1
+if [[ "${1}" = "make" ]]; then
+ forced=0
+fi
+
pushd "${BASH_SOURCE%/*}/../../Source/LexerParser" > /dev/null
for lexer in \
@@ -10,23 +15,37 @@ for lexer in \
Expr \
Fortran
do
+ cxx_file=cm${lexer}Lexer.cxx
+ h_file=cm${lexer}Lexer.h
+ in_file=cm${lexer}Lexer.in.l
+
+ if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
echo "Generating Lexer ${lexer}"
- flex --nounistd -DFLEXINT_H --noline --header-file=cm${lexer}Lexer.h -ocm${lexer}Lexer.cxx cm${lexer}Lexer.in.l
- sed -i 's/\s*$//' cm${lexer}Lexer.h cm${lexer}Lexer.cxx # remove trailing whitespaces
- sed -i '${/^$/d;}' cm${lexer}Lexer.h cm${lexer}Lexer.cxx # remove blank line at the end
- sed -i '1i#include "cmStandardLexer.h"' cm${lexer}Lexer.cxx # add cmStandardLexer.h include
+ flex --nounistd -DFLEXINT_H --noline --header-file=${h_file} -o${cxx_file} ${in_file}
+ sed -i 's/\s*$//' ${h_file} ${cxx_file} # remove trailing whitespaces
+ sed -i '${/^$/d;}' ${h_file} ${cxx_file} # remove blank line at the end
+ sed -i '1i#include "cmStandardLexer.h"' ${cxx_file} # add cmStandardLexer.h include
+ else
+ echo "Skipped generating Lexer ${lexer}"
+ fi
done
# these lexers (at the moment only the ListFileLexer) are compiled as C and do not generate a header
for lexer in ListFile
do
-
- echo "Generating Lexer ${lexer}"
- flex --nounistd -DFLEXINT_H --noline -ocm${lexer}Lexer.c cm${lexer}Lexer.in.l
- sed -i 's/\s*$//' cm${lexer}Lexer.c # remove trailing whitespaces
- sed -i '${/^$/d;}' cm${lexer}Lexer.c # remove blank line at the end
- sed -i '1i#include "cmStandardLexer.h"' cm${lexer}Lexer.c # add cmStandardLexer.h include
+ c_file=cm${lexer}Lexer.c
+ in_file=cm${lexer}Lexer.in.l
+
+ if [[ (${in_file} -nt ${c_file}) || (${forced} -gt 0) ]]; then
+ echo "Generating Lexer ${lexer}"
+ flex --nounistd -DFLEXINT_H --noline -o${c_file} ${in_file}
+ sed -i 's/\s*$//' ${c_file} # remove trailing whitespaces
+ sed -i '${/^$/d;}' ${c_file} # remove blank line at the end
+ sed -i '1i#include "cmStandardLexer.h"' ${c_file} # add cmStandardLexer.h include
+ else
+ echo "Skipped generating Lexer ${lexer}"
+ fi
done
diff --git a/Utilities/Scripts/regenerate-parsers.bash b/Utilities/Scripts/regenerate-parsers.bash
new file mode 100755
index 000000000..6fb35c028
--- /dev/null
+++ b/Utilities/Scripts/regenerate-parsers.bash
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+set -e
+
+forced=1
+if [[ "${1}" = "make" ]]; then
+ forced=0
+fi
+
+pushd "${BASH_SOURCE%/*}/../../Source/LexerParser" > /dev/null
+
+for parser in \
+ CommandArgument \
+ DependsJava \
+ Expr \
+ Fortran
+do
+ in_file=cm${parser}Parser.y
+ cxx_file=cm${parser}Parser.cxx
+ h_file=cm${parser}ParserTokens.h
+ prefix=cm${parser}_yy
+
+ if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
+ echo "Generating Parser ${parser}"
+ bison --yacc --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
+ sed -i '/\/\* Else will try to reuse/ i\
+#if 0
+/^yyerrlab1:/ a\
+#endif
+' ${cxx_file}
+ else
+ echo "Skipped generating Parser ${parser}"
+ fi
+done
+
+
+popd > /dev/null
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 28803cb01..b02180f09 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_58_0"
+readonly tag="curl-7_60_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index 2de821c2b..1cbc46371 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -17,6 +17,7 @@ if(NOT CMake_SOURCE_DIR)
endif()
project(CMakeHelp NONE)
+option(SPHINX_INFO "Build Info manual with Sphinx" OFF)
option(SPHINX_MAN "Build man pages with Sphinx" OFF)
option(SPHINX_HTML "Build html help with Sphinx" OFF)
option(SPHINX_SINGLEHTML "Build html single page help with Sphinx" OFF)
@@ -32,7 +33,7 @@ separate_arguments(sphinx_flags UNIX_COMMAND "${SPHINX_FLAGS}")
mark_as_advanced(SPHINX_TEXT)
mark_as_advanced(SPHINX_FLAGS)
-if(NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT)
+if(NOT SPHINX_INFO AND NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT)
return()
elseif(NOT SPHINX_EXECUTABLE)
message(FATAL_ERROR "SPHINX_EXECUTABLE (sphinx-build) is not found!")
@@ -66,6 +67,24 @@ endif()
if(SPHINX_TEXT)
list(APPEND doc_formats text)
endif()
+if(SPHINX_INFO)
+ find_program(MAKEINFO_EXECUTABLE
+ NAMES makeinfo
+ DOC "makeinfo tool"
+ )
+ if (NOT MAKEINFO_EXECUTABLE)
+ message(FATAL_ERROR "MAKEINFO_EXECUTABLE (makeinfo) not found!")
+ endif()
+ list(APPEND doc_formats texinfo)
+
+ # Sphinx texinfo builder supports .info, .txt, .html and .pdf output.
+ # SPHINX_INFO controls the .info output.
+ set(texinfo_extra_commands
+ COMMAND ${MAKEINFO_EXECUTABLE} --no-split -o
+ ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
+ ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.texi
+ )
+endif()
if(SPHINX_QTHELP)
find_package(PythonInterp REQUIRED)
@@ -143,6 +162,14 @@ if(CMake_SPHINX_DEPEND_ON_EXECUTABLES)
endforeach()
endif()
+if(SPHINX_INFO)
+ CMake_OPTIONAL_COMPONENT(sphinx-info)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
+ DESTINATION ${CMAKE_INFO_DIR}
+ ${COMPONENT}
+ )
+endif()
+
if(SPHINX_MAN)
file(GLOB man_rst RELATIVE ${CMake_SOURCE_DIR}/Help/manual
${CMake_SOURCE_DIR}/Help/manual/*.[1-9].rst)
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index cfda2d479..b0c8f7186 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -144,6 +144,7 @@ class _cmake_index_entry:
_cmake_index_objs = {
'command': _cmake_index_entry('command'),
+ 'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
'manual': _cmake_index_entry('manual'),
'module': _cmake_index_entry('module'),
@@ -278,7 +279,7 @@ class CMakeXRefRole(XRefRole):
# We cannot insert index nodes using the result_nodes method
# because CMakeXRefRole is processed before substitution_reference
# nodes are evaluated so target nodes (with 'ids' fields) would be
- # duplicated in each evaluted substitution replacement. The
+ # duplicated in each evaluated substitution replacement. The
# docutils substitution transform does not allow this. Instead we
# use our own CMakeXRefTransform below to add index entries after
# substitutions are completed.
@@ -324,6 +325,7 @@ class CMakeDomain(Domain):
label = 'CMake'
object_types = {
'command': ObjType('command', 'command'),
+ 'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
'variable': ObjType('variable', 'variable'),
'module': ObjType('module', 'module'),
@@ -339,6 +341,7 @@ class CMakeDomain(Domain):
}
directives = {
'command': CMakeObject,
+ 'envvar': CMakeObject,
'variable': CMakeObject,
# Other object types cannot be created except by the CMakeTransform
# 'generator': CMakeObject,
@@ -355,6 +358,7 @@ class CMakeDomain(Domain):
}
roles = {
'command': CMakeXRefRole(fix_parens = True, lowercase = True),
+ 'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
'variable': CMakeXRefRole(),
'module': CMakeXRefRole(),
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 7878ad20a..f52ccd188 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -17,6 +17,7 @@ version = '@conf_version@' # feature version
release = '@conf_release@' # full version string
primary_domain = 'cmake'
+highlight_language = 'none'
exclude_patterns = [
'dev', # ignore developer-only documentation
diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py
index 3fe3fcbe5..e63895004 100755
--- a/Utilities/Sphinx/create_identifiers.py
+++ b/Utilities/Sphinx/create_identifiers.py
@@ -21,7 +21,9 @@ newlines = []
for line in lines:
mapping = (("command", "command"),
+ ("envvar", "envvar"),
("variable", "variable"),
+ ("generator", "generator"),
("target property", "prop_tgt"),
("test property", "prop_test"),
("source file property", "prop_sf"),
diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css
index 2a326d47d..b082edec8 100644
--- a/Utilities/Sphinx/static/cmake.css
+++ b/Utilities/Sphinx/static/cmake.css
@@ -6,3 +6,13 @@
div.sphinxsidebarwrapper {
word-wrap: break-word;
}
+
+/* Make links inside parsed-literal blocks more obvious
+ by using a background color and increased line spacing
+ to make them look boxed. */
+.literal-block {
+ line-height: 1.4;
+}
+.literal-block a.reference.internal {
+ background-color: #dfdfdf;
+}
diff --git a/Utilities/cm_bzlib.h b/Utilities/cm_bzlib.h
index e7f6d8990..8669e9e6e 100644
--- a/Utilities/cm_bzlib.h
+++ b/Utilities/cm_bzlib.h
@@ -6,9 +6,9 @@
/* Use the bzip2 library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_BZIP2
-#include <bzlib.h>
+# include <bzlib.h>
#else
-#include <cmbzip2/bzlib.h>
+# include <cmbzip2/bzlib.h>
#endif
#endif
diff --git a/Utilities/cm_curl.h b/Utilities/cm_curl.h
index fc2b8ab8a..673f8ad95 100644
--- a/Utilities/cm_curl.h
+++ b/Utilities/cm_curl.h
@@ -6,9 +6,9 @@
/* Use the curl library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_CURL
-#include <curl/curl.h>
+# include <curl/curl.h>
#else
-#include <cmcurl/include/curl/curl.h>
+# include <cmcurl/include/curl/curl.h>
#endif
#endif
diff --git a/Utilities/cm_expat.h b/Utilities/cm_expat.h
index d87933715..fc5b39aba 100644
--- a/Utilities/cm_expat.h
+++ b/Utilities/cm_expat.h
@@ -6,9 +6,9 @@
/* Use the expat library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_EXPAT
-#include <expat.h>
+# include <expat.h>
#else
-#include <cmexpat/lib/expat.h>
+# include <cmexpat/lib/expat.h>
#endif
#endif
diff --git a/Utilities/cm_jsoncpp_reader.h b/Utilities/cm_jsoncpp_reader.h
index e78ec1e0c..23af65c61 100644
--- a/Utilities/cm_jsoncpp_reader.h
+++ b/Utilities/cm_jsoncpp_reader.h
@@ -6,9 +6,9 @@
/* Use the jsoncpp library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_JSONCPP
-#include <json/reader.h>
+# include <json/reader.h>
#else
-#include <cmjsoncpp/include/json/reader.h>
+# include <cmjsoncpp/include/json/reader.h>
#endif
#endif
diff --git a/Utilities/cm_jsoncpp_value.h b/Utilities/cm_jsoncpp_value.h
index cf3775859..742d99a01 100644
--- a/Utilities/cm_jsoncpp_value.h
+++ b/Utilities/cm_jsoncpp_value.h
@@ -6,9 +6,9 @@
/* Use the jsoncpp library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_JSONCPP
-#include <json/value.h>
+# include <json/value.h>
#else
-#include <cmjsoncpp/include/json/value.h>
+# include <cmjsoncpp/include/json/value.h>
#endif
#endif
diff --git a/Utilities/cm_jsoncpp_writer.h b/Utilities/cm_jsoncpp_writer.h
index 33b246847..d9e5d8217 100644
--- a/Utilities/cm_jsoncpp_writer.h
+++ b/Utilities/cm_jsoncpp_writer.h
@@ -6,9 +6,9 @@
/* Use the jsoncpp library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_JSONCPP
-#include <json/writer.h>
+# include <json/writer.h>
#else
-#include <cmjsoncpp/include/json/writer.h>
+# include <cmjsoncpp/include/json/writer.h>
#endif
#endif
diff --git a/Utilities/cm_kwiml.h b/Utilities/cm_kwiml.h
index 65cb35f96..566f67e43 100644
--- a/Utilities/cm_kwiml.h
+++ b/Utilities/cm_kwiml.h
@@ -6,11 +6,11 @@
/* Use the KWIML library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_KWIML
-#include <kwiml/abi.h>
-#include <kwiml/int.h>
+# include <kwiml/abi.h>
+# include <kwiml/int.h>
#else
-#include "KWIML/include/kwiml/abi.h"
-#include "KWIML/include/kwiml/int.h"
+# include "KWIML/include/kwiml/abi.h"
+# include "KWIML/include/kwiml/int.h"
#endif
#endif
diff --git a/Utilities/cm_libarchive.h b/Utilities/cm_libarchive.h
index 226952601..ea8e9db62 100644
--- a/Utilities/cm_libarchive.h
+++ b/Utilities/cm_libarchive.h
@@ -6,11 +6,11 @@
/* Use the libarchive configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBARCHIVE
-#include <archive.h>
-#include <archive_entry.h>
+# include <archive.h>
+# include <archive_entry.h>
#else
-#include <cmlibarchive/libarchive/archive.h>
-#include <cmlibarchive/libarchive/archive_entry.h>
+# include <cmlibarchive/libarchive/archive.h>
+# include <cmlibarchive/libarchive/archive_entry.h>
#endif
#endif
diff --git a/Utilities/cm_lzma.h b/Utilities/cm_lzma.h
index 013c724b9..0526036c6 100644
--- a/Utilities/cm_lzma.h
+++ b/Utilities/cm_lzma.h
@@ -6,9 +6,9 @@
/* Use the liblzma configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBLZMA
-#include <lzma.h>
+# include <lzma.h>
#else
-#include <cmliblzma/liblzma/api/lzma.h>
+# include <cmliblzma/liblzma/api/lzma.h>
#endif
#endif
diff --git a/Utilities/cm_rhash.h b/Utilities/cm_rhash.h
index c79362775..03d9871f7 100644
--- a/Utilities/cm_rhash.h
+++ b/Utilities/cm_rhash.h
@@ -6,9 +6,9 @@
/* Use the LibRHash library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBRHASH
-#include <rhash.h>
+# include <rhash.h>
#else
-#include <cmlibrhash/librhash/rhash.h>
+# include <cmlibrhash/librhash/rhash.h>
#endif
#endif
diff --git a/Utilities/cm_uv.h b/Utilities/cm_uv.h
index 6d4813de1..448f30d8d 100644
--- a/Utilities/cm_uv.h
+++ b/Utilities/cm_uv.h
@@ -6,9 +6,9 @@
/* Use the libuv library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBUV
-#include <uv.h>
+# include <uv.h>
#else
-#include <cmlibuv/include/uv.h>
+# include <cmlibuv/include/uv.h>
#endif
#endif
diff --git a/Utilities/cm_xmlrpc.h b/Utilities/cm_xmlrpc.h
index 08db89f60..932066aaa 100644
--- a/Utilities/cm_xmlrpc.h
+++ b/Utilities/cm_xmlrpc.h
@@ -6,8 +6,8 @@
/* Use the xmlrpc library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CTEST_USE_XMLRPC
-#include <xmlrpc.h>
-#include <xmlrpc_client.h>
+# include <xmlrpc.h>
+# include <xmlrpc_client.h>
#endif
#endif
diff --git a/Utilities/cm_zlib.h b/Utilities/cm_zlib.h
index 2aee9f194..2314183b1 100644
--- a/Utilities/cm_zlib.h
+++ b/Utilities/cm_zlib.h
@@ -6,9 +6,9 @@
/* Use the zlib library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_ZLIB
-#include <zlib.h>
+# include <zlib.h>
#else
-#include <cmzlib/zlib.h>
+# include <cmzlib/zlib.h>
#endif
#endif
diff --git a/Utilities/cmcurl/CMake/FindBrotli.cmake b/Utilities/cmcurl/CMake/FindBrotli.cmake
new file mode 100644
index 000000000..351b8f757
--- /dev/null
+++ b/Utilities/cmcurl/CMake/FindBrotli.cmake
@@ -0,0 +1,20 @@
+include(FindPackageHandleStandardArgs)
+
+find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
+
+find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
+find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
+
+find_package_handle_standard_args(BROTLI
+ FOUND_VAR
+ BROTLI_FOUND
+ REQUIRED_VARS
+ BROTLIDEC_LIBRARY
+ BROTLICOMMON_LIBRARY
+ BROTLI_INCLUDE_DIR
+ FAIL_MESSAGE
+ "Could NOT find BROTLI"
+)
+
+set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
+set(BROTLI_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIDEC_LIBRARY})
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 148ca5d33..012821415 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -90,7 +90,7 @@ endif()
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -328,16 +328,6 @@ if(BORLAND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
endif(BORLAND)
-if(CURL_WERROR)
- if(MSVC_VERSION)
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX")
- else()
- # this assumes clang or gcc style options
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
- endif()
-endif(CURL_WERROR)
-
# If we are on AIX, do the _ALL_SOURCE magic
if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
set(_ALL_SOURCE 1)
@@ -398,6 +388,7 @@ check_function_exists(gethostname HAVE_GETHOSTNAME)
if(WIN32)
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
+ list(APPEND CURL_LIBS "advapi32")
endif()
# check SSL libraries
@@ -644,6 +635,18 @@ if(CURL_SPECIAL_LIBZ)
set(HAVE_ZLIB_H 0)
endif()
+option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
+set(HAVE_BROTLI OFF)
+if(CURL_BROTLI)
+ find_package(BROTLI QUIET)
+ if(BROTLI_FOUND)
+ set(HAVE_BROTLI ON)
+ list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
+ include_directories(${BROTLI_INCLUDE_DIRS})
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
+ endif()
+endif()
+
#libSSH2
option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
mark_as_advanced(CMAKE_USE_LIBSSH2)
@@ -1237,6 +1240,15 @@ if(MSVC)
endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
endif(MSVC)
+if(CURL_WERROR)
+ if(MSVC_VERSION)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
+ else()
+ # this assumes clang or gcc style options
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+ endif()
+endif(CURL_WERROR)
+
# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index a96124d1c..10e5c494b 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -245,7 +245,9 @@ typedef size_t (*curl_write_callback)(char *buffer,
size_t nitems,
void *outstream);
-
+/* This callback will be called when a new resolver request is made */
+typedef int (*curl_resolver_start_callback)(void *resolver_state,
+ void *reserved, void *userdata);
/* enumeration of file types */
typedef enum {
@@ -577,6 +579,8 @@ typedef enum {
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
*/
+ CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from
+ inside a callback */
CURL_LAST /* never use! */
} CURLcode;
@@ -789,6 +793,11 @@ typedef enum {
SSL backends where such behavior is present. */
#define CURLSSLOPT_NO_REVOKE (1<<1)
+/* The default connection attempt delay in milliseconds for happy eyeballs.
+ CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
+ this value, keep them in sync. */
+#define CURL_HET_DEFAULT 200L
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
@@ -1662,7 +1671,7 @@ typedef enum {
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
- /* Set the local IPv4 address to use for outgoing DNS requests.
+ /* Set the local IPv6 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
@@ -1819,6 +1828,25 @@ typedef enum {
/* Post MIME data. */
CINIT(MIMEPOST, OBJECTPOINT, 269),
+ /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
+ seconds since 1 Jan 1970. */
+ CINIT(TIMEVALUE_LARGE, OFF_T, 270),
+
+ /* Head start in milliseconds to give happy eyeballs. */
+ CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
+
+ /* Function that will be called before a resolver request is made */
+ CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
+
+ /* User data to pass to the resolver start callback. */
+ CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
+
+ /* send HAProxy PROXY protocol header? */
+ CINIT(HAPROXYPROTOCOL, LONG, 274),
+
+ /* shuffle addresses before use when DNS returns multiple */
+ CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2459,6 +2487,7 @@ typedef enum {
CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index a47c45494..2d1505aa4 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,16 +26,16 @@
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, <daniel@haxx.se>."
+#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.58.0"
+#define LIBCURL_VERSION "7.60.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 58
+#define LIBCURL_VERSION_MINOR 60
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x073A00
+#define LIBCURL_VERSION_NUM 0x073C00
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h
index 911c91dd1..b19dbaf79 100644
--- a/Utilities/cmcurl/include/curl/multi.h
+++ b/Utilities/cmcurl/include/curl/multi.h
@@ -70,6 +70,8 @@ typedef enum {
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
+ CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
+ callback */
CURLM_LAST
} CURLMcode;
@@ -184,8 +186,8 @@ CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
- * still have occurred problems on invidual transfers even when this
- * returns OK.
+ * still have occurred problems on individual transfers even when
+ * this returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index 07bbd9ca9..eac4cfeb6 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -300,7 +300,9 @@
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
- defined(__i386) || defined(__sparcv8))
+ defined(__i386) || \
+ defined(__sparcv8) || \
+ defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 10c74c764..3a0f253f6 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -54,6 +54,9 @@ __extension__ ({ \
if(_curl_is_write_cb_option(_curl_opt)) \
if(!_curl_is_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
+ if(!_curl_is_resolver_start_callback(value)) \
+ _curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!_curl_is_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
@@ -170,6 +173,10 @@ _CURL_WARNING(_curl_easy_setopt_err_string,
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
+ "curl_easy_setopt expects a "
+ "curl_resolver_start_callback argument for this option"
+ )
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
@@ -354,6 +361,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_RESOLVER_START_DATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
@@ -504,6 +512,11 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func) *, type))
+/* evaluates to true if expr is of type curl_resolver_start_callback */
+#define _curl_is_resolver_start_callback(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_resolver_start_callback))
+
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \
(_curl_is_NULL(expr) || \
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 61e80cf52..61c23411d 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,8 +29,8 @@ LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c \
- vtls/cyassl.c vtls/schannel.c vtls/darwinssl.c vtls/gskit.c \
- vtls/mbedtls.c
+ vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \
+ vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
@@ -46,7 +46,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
- ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
+ ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
openldap.c curl_gethostname.c gopher.c idn_win32.c \
@@ -54,7 +54,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
- mime.c sha256.c setopt.c curl_path.c
+ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
@@ -74,7 +74,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \
- curl_path.h
+ curl_path.h curl_ctype.h curl_range.h
LIB_RCFILES = libcurl.rc
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 1ac3fc809..b11fab246 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,6 +79,10 @@
#include "curl_memory.h"
#include "memdebug.h"
+struct resdata {
+ struct curltime start;
+};
+
/*
* Curl_resolver_global_init()
* Called from curl_global_init() to initialize global resolver environment.
@@ -102,11 +106,13 @@ void Curl_resolver_global_cleanup(void)
* Curl_resolver_init()
* Called from curl_easy_init() -> Curl_open() to initialize resolver
* URL-state specific environment ('resolver' member of the UrlState
- * structure). Does nothing here.
+ * structure).
*/
CURLcode Curl_resolver_init(void **resolver)
{
- (void)resolver;
+ *resolver = calloc(1, sizeof(struct resdata));
+ if(!*resolver)
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
@@ -114,24 +120,22 @@ CURLcode Curl_resolver_init(void **resolver)
* Curl_resolver_cleanup()
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
* URL-state specific environment ('resolver' member of the UrlState
- * structure). Does nothing here.
+ * structure).
*/
void Curl_resolver_cleanup(void *resolver)
{
- (void)resolver;
+ free(resolver);
}
/*
* Curl_resolver_duphandle()
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific
- * environment ('resolver' member of the UrlState structure). Does nothing
- * here.
+ * environment ('resolver' member of the UrlState structure).
*/
int Curl_resolver_duphandle(void **to, void *from)
{
- (void)to;
(void)from;
- return CURLE_OK;
+ return Curl_resolver_init(to);
}
static void destroy_async_data(struct Curl_async *);
@@ -561,9 +565,22 @@ int Curl_resolver_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
- (void)conn;
+ time_t milli;
+ timediff_t ms;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
(void)socks;
(void)numsocks;
+ ms = Curl_timediff(Curl_now(), reslv->start);
+ if(ms < 10)
+ milli = ms/3;
+ else if(ms <= 50)
+ milli = 10;
+ else if(ms <= 250)
+ milli = 50;
+ else
+ milli = 200;
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return 0;
}
@@ -577,6 +594,8 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
struct in_addr in;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
@@ -584,14 +603,17 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(AF_INET, &in, hostname, port);
+ reslv->start = Curl_now();
+
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- /* fall-back to blocking version */
- return Curl_ipv4_resolve_r(hostname, port);
+ failf(conn->data, "getaddrinfo() thread failed\n");
+
+ return NULL;
}
#else /* !HAVE_GETADDRINFO */
@@ -605,10 +627,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
struct addrinfo hints;
- Curl_addrinfo *res;
- int error;
char sbuf[12];
int pf = PF_INET;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
@@ -658,27 +680,16 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
snprintf(sbuf, sizeof(sbuf), "%d", port);
+ reslv->start = Curl_now();
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- /* fall-back to blocking version */
- infof(conn->data, "init_resolve_thread() failed for %s; %s\n",
- hostname, Curl_strerror(conn, errno));
-
- error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
- if(error) {
- infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n",
- hostname, port, Curl_strerror(conn, SOCKERRNO));
- return NULL;
- }
- else {
- Curl_addrinfo_set_port(res, port);
- }
+ failf(data, "getaddrinfo() thread failed to start\n");
+ return NULL;
- return res;
}
#endif /* !HAVE_GETADDRINFO */
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 3edb71eb7..1a27ae135 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -619,8 +619,8 @@ void Curl_persistconninfo(struct connectdata *conn)
/* retrieves ip address and port from a sockaddr structure.
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-static bool getaddressinfo(struct sockaddr *sa, char *addr,
- long *port)
+bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
+ long *port)
{
unsigned short us_port;
struct sockaddr_in *si = NULL;
@@ -700,16 +700,16 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
return;
}
- if(!getaddressinfo((struct sockaddr*)&ssrem,
- conn->primary_ip, &conn->primary_port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
+ conn->primary_ip, &conn->primary_port)) {
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
return;
}
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
- if(!getaddressinfo((struct sockaddr*)&ssloc,
- conn->local_ip, &conn->local_port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
+ conn->local_ip, &conn->local_port)) {
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
return;
@@ -783,7 +783,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* should we try another protocol family? */
if(i == 0 && conn->tempaddr[1] == NULL &&
- Curl_timediff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
+ (Curl_timediff(now, conn->connecttime) >=
+ data->set.happy_eyeballs_timeout)) {
trynextip(conn, sockindex, 1);
}
}
@@ -1005,8 +1006,8 @@ static CURLcode singleipconnect(struct connectdata *conn,
return CURLE_OK;
/* store remote address and port used in this connection attempt */
- if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
- ipaddress, &port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
+ ipaddress, &port)) {
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
@@ -1033,9 +1034,11 @@ static CURLcode singleipconnect(struct connectdata *conn,
if(data->set.fsockopt) {
/* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
error = data->set.fsockopt(data->set.sockopt_client,
sockfd,
CURLSOCKTYPE_IPCXN);
+ Curl_set_in_callback(data, false);
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
isconnected = TRUE;
@@ -1204,7 +1207,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
data->info.numconnects++; /* to track the number of connections made */
- Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
+ Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
+ EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK;
}
@@ -1311,8 +1315,12 @@ int Curl_closesocket(struct connectdata *conn,
status */
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
else {
+ int rc;
Curl_multi_closed(conn, sock);
- return conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(conn->data, true);
+ rc = conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(conn->data, false);
+ return rc;
}
}
@@ -1363,7 +1371,7 @@ CURLcode Curl_socket(struct connectdata *conn,
addr->addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
- if(data->set.fopensocket)
+ if(data->set.fopensocket) {
/*
* If the opensocket callback is set, all the destination address
* information is passed to the callback. Depending on this information the
@@ -1373,9 +1381,12 @@ CURLcode Curl_socket(struct connectdata *conn,
* might have been changed and this 'new' address will actually be used
* here to connect.
*/
+ Curl_set_in_callback(data, true);
*sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
(struct curl_sockaddr *)addr);
+ Curl_set_in_callback(data, false);
+ }
else
/* opensocket callback not set, so simply create the socket now */
*sockfd = socket(addr->family, addr->socktype, addr->protocol);
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 397448636..193dc6397 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -41,8 +41,6 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
bool duringconnect);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
-#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
- IPv4/IPv6 connection attempts */
/*
* Used to extract socket and connectdata struct for the most recent
@@ -78,6 +76,11 @@ void Curl_persistconninfo(struct connectdata *conn);
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
/*
+ * Get presentation format IP address and port from a sockaddr.
+ */
+bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port);
+
+/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index 46bef0ca9..7c979efcc 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -726,7 +726,7 @@ static void identity_close_writer(struct connectdata *conn,
static const content_encoding identity_encoding = {
"identity",
- NULL,
+ "none",
identity_init_writer,
identity_unencode_write,
identity_close_writer,
@@ -873,10 +873,9 @@ static contenc_writer *new_unencoding_writer(struct connectdata *conn,
contenc_writer *downstream)
{
size_t sz = offsetof(contenc_writer, params) + handler->paramsize;
- contenc_writer *writer = (contenc_writer *) malloc(sz);
+ contenc_writer *writer = (contenc_writer *) calloc(1, sz);
if(writer) {
- memset(writer, 0, sz);
writer->handler = handler;
writer->downstream = downstream;
if(handler->init_writer(conn, writer)) {
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 5f0f145fc..2c028b381 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -143,6 +143,28 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
}
/*
+ * Return true if the given string is an IP(v4|v6) address.
+ */
+static bool isip(const char *domain)
+{
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+
+ if(Curl_inet_pton(AF_INET, domain, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, domain, &addr6)
+#endif
+ ) {
+ /* domain name given as IP address */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
* matching cookie path and url path
* RFC6265 5.1.4 Paths and Path-Match
*/
@@ -218,6 +240,62 @@ pathmatched:
}
/*
+ * Return the top-level domain, for optimal hashing.
+ */
+static const char *get_top_domain(const char * const domain, size_t *outlen)
+{
+ size_t len;
+ const char *first = NULL, *last;
+
+ if(!domain)
+ return NULL;
+
+ len = strlen(domain);
+ last = memrchr(domain, '.', len);
+ if(last) {
+ first = memrchr(domain, '.', (size_t) (last - domain));
+ if(first)
+ len -= (size_t) (++first - domain);
+ }
+
+ if(outlen)
+ *outlen = len;
+
+ return first? first: domain;
+}
+
+/*
+ * A case-insensitive hash for the cookie domains.
+ */
+static size_t cookie_hash_domain(const char *domain, const size_t len)
+{
+ const char *end = domain + len;
+ size_t h = 5381;
+
+ while(domain < end) {
+ h += h << 5;
+ h ^= Curl_raw_toupper(*domain++);
+ }
+
+ return (h % COOKIE_HASH_SIZE);
+}
+
+/*
+ * Hash this domain.
+ */
+static size_t cookiehash(const char * const domain)
+{
+ const char *top;
+ size_t len;
+
+ if(!domain || isip(domain))
+ return 0;
+
+ top = get_top_domain(domain, &len);
+ return cookie_hash_domain(top, len);
+}
+
+/*
* cookie path sanitize
*/
static char *sanitize_cookie_path(const char *cookie_path)
@@ -303,48 +381,29 @@ static void remove_expired(struct CookieInfo *cookies)
{
struct Cookie *co, *nx, *pv;
curl_off_t now = (curl_off_t)time(NULL);
-
- co = cookies->cookies;
- pv = NULL;
- while(co) {
- nx = co->next;
- if(co->expires && co->expires < now) {
- if(!pv) {
- cookies->cookies = co->next;
+ unsigned int i;
+
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ co = cookies->cookies[i];
+ pv = NULL;
+ while(co) {
+ nx = co->next;
+ if(co->expires && co->expires < now) {
+ if(!pv) {
+ cookies->cookies[i] = co->next;
+ }
+ else {
+ pv->next = co->next;
+ }
+ cookies->numcookies--;
+ freecookie(co);
}
else {
- pv->next = co->next;
+ pv = co;
}
- cookies->numcookies--;
- freecookie(co);
- }
- else {
- pv = co;
+ co = nx;
}
- co = nx;
- }
-}
-
-/*
- * Return true if the given string is an IP(v4|v6) address.
- */
-static bool isip(const char *domain)
-{
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
-
- if(Curl_inet_pton(AF_INET, domain, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, domain, &addr6)
-#endif
- ) {
- /* domain name given as IP address */
- return TRUE;
}
-
- return FALSE;
}
/****************************************************************************
@@ -368,6 +427,7 @@ Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
+ bool noexpire, /* if TRUE, skip remove_expired() */
char *lineptr, /* first character of the line */
const char *domain, /* default domain */
const char *path) /* full path used when this cookie is set,
@@ -380,6 +440,7 @@ Curl_cookie_add(struct Curl_easy *data,
time_t now = time(NULL);
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
+ size_t myhash;
#ifdef USE_LIBPSL
const psl_ctx_t *psl;
@@ -430,9 +491,6 @@ Curl_cookie_add(struct Curl_easy *data,
size_t nlen = strlen(name);
const char *endofn = &ptr[ nlen ];
- infof(data, "cookie size: name/val %d + %d bytes\n",
- nlen, len);
-
if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
((nlen + len) > MAX_NAME)) {
/* too long individual name or contents, or too long combination of
@@ -470,10 +528,16 @@ Curl_cookie_add(struct Curl_easy *data,
while(*whatptr && ISBLANK(*whatptr))
whatptr++;
- if(!co->name && sep) {
+ if(!co->name) {
/* The very first name/value pair is the actual cookie name */
+ if(!sep) {
+ /* Bad name/value pair. */
+ badcookie = TRUE;
+ break;
+ }
co->name = strdup(name);
co->value = strdup(whatptr);
+ done = TRUE;
if(!co->name || !co->value) {
badcookie = TRUE;
break;
@@ -822,7 +886,8 @@ Curl_cookie_add(struct Curl_easy *data,
the same domain and path as this */
/* at first, remove expired cookies */
- remove_expired(c);
+ if(!noexpire)
+ remove_expired(c);
#ifdef USE_LIBPSL
/* Check if the domain is a Public Suffix and if yes, ignore the cookie.
@@ -839,7 +904,8 @@ Curl_cookie_add(struct Curl_easy *data,
}
#endif
- clist = c->cookies;
+ myhash = cookiehash(co->domain);
+ clist = c->cookies[myhash];
replace_old = FALSE;
while(clist) {
if(strcasecompare(clist->name, co->name)) {
@@ -925,7 +991,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(lastc)
lastc->next = co;
else
- c->cookies = co;
+ c->cookies[myhash] = co;
c->numcookies++; /* one more cookie in the jar */
}
@@ -1029,9 +1095,10 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
- Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
+ Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */
+ remove_expired(c); /* run this once, not on every cookie */
if(fromfile)
fclose(fp);
@@ -1137,8 +1204,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
+ const size_t myhash = cookiehash(host);
- if(!c || !c->cookies)
+ if(!c || !c->cookies[myhash])
return NULL; /* no cookie struct or no cookies in the struct */
/* at first, remove expired cookies */
@@ -1147,7 +1215,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* check if host is an IP(v4|v6) address */
is_ip = isip(host);
- co = c->cookies;
+ co = c->cookies[myhash];
while(co) {
/* only process this cookie if it is not expired or had no expire
@@ -1235,8 +1303,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
- Curl_cookie_freelist(cookies->cookies);
- cookies->cookies = NULL;
+ unsigned int i;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ Curl_cookie_freelist(cookies->cookies[i]);
+ cookies->cookies[i] = NULL;
+ }
cookies->numcookies = 0;
}
}
@@ -1270,31 +1341,37 @@ void Curl_cookie_freelist(struct Cookie *co)
void Curl_cookie_clearsess(struct CookieInfo *cookies)
{
struct Cookie *first, *curr, *next, *prev = NULL;
+ unsigned int i;
- if(!cookies || !cookies->cookies)
+ if(!cookies)
return;
- first = curr = prev = cookies->cookies;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ if(!cookies->cookies[i])
+ continue;
- for(; curr; curr = next) {
- next = curr->next;
- if(!curr->expires) {
- if(first == curr)
- first = next;
+ first = curr = prev = cookies->cookies[i];
- if(prev == curr)
- prev = next;
- else
- prev->next = next;
+ for(; curr; curr = next) {
+ next = curr->next;
+ if(!curr->expires) {
+ if(first == curr)
+ first = next;
+
+ if(prev == curr)
+ prev = next;
+ else
+ prev->next = next;
- freecookie(curr);
- cookies->numcookies--;
+ freecookie(curr);
+ cookies->numcookies--;
+ }
+ else
+ prev = curr;
}
- else
- prev = curr;
- }
- cookies->cookies = first;
+ cookies->cookies[i] = first;
+ }
}
@@ -1307,9 +1384,12 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
+ unsigned int i;
+
if(c) {
free(c->filename);
- Curl_cookie_freelist(c->cookies);
+ for(i = 0; i < COOKIE_HASH_SIZE; i++)
+ Curl_cookie_freelist(c->cookies[i]);
free(c); /* free the base struct as well */
}
}
@@ -1358,6 +1438,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
FILE *out;
bool use_stdout = FALSE;
char *format_ptr;
+ unsigned int i;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
@@ -1367,6 +1448,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
/* at first, remove expired cookies */
remove_expired(c);
+ /* make sure we still have cookies after expiration */
+ if(0 == c->numcookies)
+ return 0;
+
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
@@ -1383,18 +1468,20 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
- for(co = c->cookies; co; co = co->next) {
- if(!co->domain)
- continue;
- format_ptr = get_netscape_format(co);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
- if(!use_stdout)
- fclose(out);
- return 1;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(co = c->cookies[i]; co; co = co->next) {
+ if(!co->domain)
+ continue;
+ format_ptr = get_netscape_format(co);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
}
- fprintf(out, "%s\n", format_ptr);
- free(format_ptr);
}
if(!use_stdout)
@@ -1409,26 +1496,29 @@ static struct curl_slist *cookie_list(struct Curl_easy *data)
struct curl_slist *beg;
struct Cookie *c;
char *line;
+ unsigned int i;
if((data->cookies == NULL) ||
(data->cookies->numcookies == 0))
return NULL;
- for(c = data->cookies->cookies; c; c = c->next) {
- if(!c->domain)
- continue;
- line = get_netscape_format(c);
- if(!line) {
- curl_slist_free_all(list);
- return NULL;
- }
- beg = Curl_slist_append_nodup(list, line);
- if(!beg) {
- free(line);
- curl_slist_free_all(list);
- return NULL;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(c = data->cookies->cookies[i]; c; c = c->next) {
+ if(!c->domain)
+ continue;
+ line = get_netscape_format(c);
+ if(!line) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ beg = Curl_slist_append_nodup(list, line);
+ if(!beg) {
+ free(line);
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
}
- list = beg;
}
return list;
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index cb50b71c6..79b5928dc 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -45,9 +45,11 @@ struct Cookie {
bool httponly; /* true if the httponly directive is present */
};
+#define COOKIE_HASH_SIZE 256
+
struct CookieInfo {
/* linked list of cookies we know of */
- struct Cookie *cookies;
+ struct Cookie *cookies[COOKIE_HASH_SIZE];
char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
@@ -67,7 +69,6 @@ struct CookieInfo {
*/
#define MAX_COOKIE_LINE 5000
-#define MAX_COOKIE_LINE_TXT "4999"
/* This is the maximum length of a cookie name or content we deal with: */
#define MAX_NAME 4096
@@ -80,7 +81,8 @@ struct Curl_easy;
*/
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
- struct CookieInfo *, bool header, char *lineptr,
+ struct CookieInfo *, bool header, bool noexpiry,
+ char *lineptr,
const char *domain, const char *path);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index ec76f7540..55d5a3942 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,6 +50,10 @@
# define in_addr_t unsigned long
#endif
+#if defined(WIN32) && defined(USE_UNIX_SOCKETS)
+#include <afunix.h>
+#endif
+
#include <stddef.h>
#include "curl_addrinfo.h"
@@ -341,7 +345,7 @@ Curl_he2ai(const struct hostent *he, int port)
addr = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
- addr->sin_family = (unsigned short)(he->h_addrtype);
+ addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr->sin_port = htons((unsigned short)port);
break;
@@ -350,7 +354,7 @@ Curl_he2ai(const struct hostent *he, int port)
addr6 = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
- addr6->sin6_family = (unsigned short)(he->h_addrtype);
+ addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 1d1e3d791..24d1ca0bd 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -389,6 +389,9 @@
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
+/* if brotli is available */
+#cmakedefine HAVE_BROTLI 1
+
/* if your compiler supports LL */
#cmakedefine HAVE_LL 1
diff --git a/Utilities/cmcurl/lib/curl_ctype.c b/Utilities/cmcurl/lib/curl_ctype.c
new file mode 100644
index 000000000..1a47fb5e6
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_ctype.c
@@ -0,0 +1,133 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DOES_CONVERSIONS
+
+#undef _U
+#define _U (1<<0) /* upper case */
+#undef _L
+#define _L (1<<1) /* lower case */
+#undef _N
+#define _N (1<<2) /* decimal numerical digit */
+#undef _S
+#define _S (1<<3) /* space */
+#undef _P
+#define _P (1<<4) /* punctuation */
+#undef _C
+#define _C (1<<5) /* control */
+#undef _X
+#define _X (1<<6) /* hexadecimal letter */
+#undef _B
+#define _B (1<<7) /* blank */
+
+static const unsigned char ascii[128] = {
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _S|_B, _P, _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P, _P, _P,
+ _N, _N, _N, _N, _N, _N, _N, _N,
+ _N, _N, _P, _P, _P, _P, _P, _P,
+ _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _P, _P, _P, _P, _P,
+ _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _P, _P, _P, _P, _C
+};
+
+int Curl_isspace(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & _S);
+}
+
+int Curl_isdigit(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & _N);
+}
+
+int Curl_isalnum(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_U|_L));
+}
+
+int Curl_isxdigit(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_X));
+}
+
+int Curl_isgraph(int c)
+{
+ if((c < 0) || (c >= 0x80) || (c == ' '))
+ return FALSE;
+ return (ascii[c] & (_N|_X|_U|_L|_P|_S));
+}
+
+int Curl_isprint(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_X|_U|_L|_P|_S));
+}
+
+int Curl_isalpha(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_U|_L));
+}
+
+int Curl_isupper(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_U));
+}
+
+int Curl_islower(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_L));
+}
+
+int Curl_iscntrl(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_C));
+}
+
+#endif /* !CURL_DOES_CONVERSIONS */
diff --git a/Utilities/cmcurl/lib/curl_ctype.h b/Utilities/cmcurl/lib/curl_ctype.h
new file mode 100644
index 000000000..6e94bb1b4
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_ctype.h
@@ -0,0 +1,81 @@
+#ifndef HEADER_CURL_CTYPE_H
+#define HEADER_CURL_CTYPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+/*
+ * Uppercase macro versions of ANSI/ISO is*() functions/macros which
+ * avoid negative number inputs with argument byte codes > 127.
+ *
+ * For non-ASCII platforms the C library character classification routines
+ * are used despite being locale-dependent, because this is better than
+ * not to work at all.
+ */
+#include <ctype.h>
+
+#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (islower((int) ((unsigned char)x)))
+#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x)))
+#define ISASCII(x) (isascii((int) ((unsigned char)x)))
+
+#else
+
+int Curl_isspace(int c);
+int Curl_isdigit(int c);
+int Curl_isalnum(int c);
+int Curl_isxdigit(int c);
+int Curl_isgraph(int c);
+int Curl_isprint(int c);
+int Curl_isalpha(int c);
+int Curl_isupper(int c);
+int Curl_islower(int c);
+int Curl_iscntrl(int c);
+
+#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
+#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
+#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
+
+#endif
+
+#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
+ (((unsigned char)x) == '\t'))
+
+#endif /* HEADER_CURL_CTYPE_H */
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index f33bba1f1..0179a4f71 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -47,14 +47,7 @@
#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
typedef enum {
- CURLFNM_LOOP_DEFAULT = 0,
- CURLFNM_LOOP_BACKSLASH
-} loop_state;
-
-typedef enum {
CURLFNM_SCHS_DEFAULT = 0,
- CURLFNM_SCHS_MAYRANGE,
- CURLFNM_SCHS_MAYRANGE2,
CURLFNM_SCHS_RIGHTBR,
CURLFNM_SCHS_RIGHTBRLEFTBR
} setcharset_state;
@@ -64,6 +57,13 @@ typedef enum {
CURLFNM_PKW_DDOT
} parsekey_state;
+typedef enum {
+ CCLASS_OTHER = 0,
+ CCLASS_DIGIT,
+ CCLASS_UPPER,
+ CCLASS_LOWER
+} char_class;
+
#define SETCHARSET_OK 1
#define SETCHARSET_FAIL 0
@@ -81,12 +81,12 @@ static int parsekeyword(unsigned char **pattern, unsigned char *charset)
return SETCHARSET_FAIL;
switch(state) {
case CURLFNM_PKW_INIT:
- if(ISALPHA(c) && ISLOWER(c))
+ if(ISLOWER(c))
keyword[i] = c;
else if(c == ':')
state = CURLFNM_PKW_DDOT;
else
- return 0;
+ return SETCHARSET_FAIL;
break;
case CURLFNM_PKW_DDOT:
if(c == ']')
@@ -123,14 +123,48 @@ static int parsekeyword(unsigned char **pattern, unsigned char *charset)
return SETCHARSET_OK;
}
+/* Return the character class. */
+static char_class charclass(unsigned char c)
+{
+ if(ISUPPER(c))
+ return CCLASS_UPPER;
+ if(ISLOWER(c))
+ return CCLASS_LOWER;
+ if(ISDIGIT(c))
+ return CCLASS_DIGIT;
+ return CCLASS_OTHER;
+}
+
+/* Include a character or a range in set. */
+static void setcharorrange(unsigned char **pp, unsigned char *charset)
+{
+ unsigned char *p = (*pp)++;
+ unsigned char c = *p++;
+
+ charset[c] = 1;
+ if(ISALNUM(c) && *p++ == '-') {
+ char_class cc = charclass(c);
+ unsigned char endrange = *p++;
+
+ if(endrange == '\\')
+ endrange = *p++;
+ if(endrange >= c && charclass(endrange) == cc) {
+ while(c++ != endrange)
+ if(charclass(c) == cc) /* Chars in class may be not consecutive. */
+ charset[c] = 1;
+ *pp = p;
+ }
+ }
+}
+
/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
static int setcharset(unsigned char **p, unsigned char *charset)
{
setcharset_state state = CURLFNM_SCHS_DEFAULT;
- unsigned char rangestart = 0;
- unsigned char lastchar = 0;
bool something_found = FALSE;
unsigned char c;
+
+ memset(charset, 0, CURLFNM_CHSET_SIZE);
for(;;) {
c = **p;
if(!c)
@@ -138,14 +172,7 @@ static int setcharset(unsigned char **p, unsigned char *charset)
switch(state) {
case CURLFNM_SCHS_DEFAULT:
- if(ISALNUM(c)) { /* ASCII value */
- rangestart = c;
- charset[c] = 1;
- (*p)++;
- state = CURLFNM_SCHS_MAYRANGE;
- something_found = TRUE;
- }
- else if(c == ']') {
+ if(c == ']') {
if(something_found)
return SETCHARSET_OK;
something_found = TRUE;
@@ -154,26 +181,16 @@ static int setcharset(unsigned char **p, unsigned char *charset)
(*p)++;
}
else if(c == '[') {
- char c2 = *((*p) + 1);
- if(c2 == ':') { /* there has to be a keyword */
- (*p) += 2;
- if(parsekeyword(p, charset)) {
- state = CURLFNM_SCHS_DEFAULT;
- }
- else
- return SETCHARSET_FAIL;
- }
+ unsigned char *pp = *p + 1;
+
+ if(*pp++ == ':' && parsekeyword(&pp, charset))
+ *p = pp;
else {
charset[c] = 1;
(*p)++;
}
something_found = TRUE;
}
- else if(c == '?' || c == '*') {
- something_found = TRUE;
- charset[c] = 1;
- (*p)++;
- }
else if(c == '^' || c == '!') {
if(!something_found) {
if(charset[CURLFNM_NEGATE]) {
@@ -189,82 +206,17 @@ static int setcharset(unsigned char **p, unsigned char *charset)
}
else if(c == '\\') {
c = *(++(*p));
- if(ISPRINT((c))) {
- something_found = TRUE;
- state = CURLFNM_SCHS_MAYRANGE;
- charset[c] = 1;
- rangestart = c;
- (*p)++;
- }
+ if(c)
+ setcharorrange(p, charset);
else
- return SETCHARSET_FAIL;
+ charset['\\'] = 1;
+ something_found = TRUE;
}
else {
- charset[c] = 1;
- (*p)++;
+ setcharorrange(p, charset);
something_found = TRUE;
}
break;
- case CURLFNM_SCHS_MAYRANGE:
- if(c == '-') {
- charset[c] = 1;
- (*p)++;
- lastchar = '-';
- state = CURLFNM_SCHS_MAYRANGE2;
- }
- else if(c == '[') {
- state = CURLFNM_SCHS_DEFAULT;
- }
- else if(ISALNUM(c)) {
- charset[c] = 1;
- (*p)++;
- }
- else if(c == '\\') {
- c = *(++(*p));
- if(ISPRINT(c)) {
- charset[c] = 1;
- (*p)++;
- }
- else
- return SETCHARSET_FAIL;
- }
- else if(c == ']') {
- return SETCHARSET_OK;
- }
- else
- return SETCHARSET_FAIL;
- break;
- case CURLFNM_SCHS_MAYRANGE2:
- if(c == ']') {
- return SETCHARSET_OK;
- }
- else if(c == '\\') {
- c = *(++(*p));
- if(ISPRINT(c)) {
- charset[c] = 1;
- state = CURLFNM_SCHS_DEFAULT;
- (*p)++;
- }
- else
- return SETCHARSET_FAIL;
- }
- else if(c >= rangestart) {
- if((ISLOWER(c) && ISLOWER(rangestart)) ||
- (ISDIGIT(c) && ISDIGIT(rangestart)) ||
- (ISUPPER(c) && ISUPPER(rangestart))) {
- charset[lastchar] = 0;
- rangestart++;
- while(rangestart++ <= c)
- charset[rangestart-1] = 1;
- (*p)++;
- state = CURLFNM_SCHS_DEFAULT;
- }
- else
- return SETCHARSET_FAIL;
- }
- else
- return SETCHARSET_FAIL;
- break;
case CURLFNM_SCHS_RIGHTBR:
if(c == '[') {
state = CURLFNM_SCHS_RIGHTBRLEFTBR;
@@ -286,14 +238,11 @@ static int setcharset(unsigned char **p, unsigned char *charset)
goto fail;
break;
case CURLFNM_SCHS_RIGHTBRLEFTBR:
- if(c == ']') {
+ if(c == ']')
return SETCHARSET_OK;
- }
- else {
- state = CURLFNM_SCHS_DEFAULT;
- charset[c] = 1;
- (*p)++;
- }
+ state = CURLFNM_SCHS_DEFAULT;
+ charset[c] = 1;
+ (*p)++;
break;
}
}
@@ -304,107 +253,93 @@ fail:
static int loop(const unsigned char *pattern, const unsigned char *string,
int maxstars)
{
- loop_state state = CURLFNM_LOOP_DEFAULT;
unsigned char *p = (unsigned char *)pattern;
unsigned char *s = (unsigned char *)string;
unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
- int rc = 0;
for(;;) {
- switch(state) {
- case CURLFNM_LOOP_DEFAULT:
- if(*p == '*') {
- if(!maxstars)
- return CURL_FNMATCH_NOMATCH;
- while(*(p + 1) == '*') /* eliminate multiple stars */
- p++;
- if(*s == '\0' && *(p + 1) == '\0')
- return CURL_FNMATCH_MATCH;
- rc = loop(p + 1, s, maxstars - 1); /* *.txt matches .txt <=>
- .txt matches .txt */
- if(rc == CURL_FNMATCH_MATCH)
+ unsigned char *pp;
+
+ switch(*p) {
+ case '*':
+ if(!maxstars)
+ return CURL_FNMATCH_NOMATCH;
+ /* Regroup consecutive stars and question marks. This can be done because
+ '*?*?*' can be expressed as '??*'. */
+ for(;;) {
+ if(*++p == '\0')
return CURL_FNMATCH_MATCH;
- if(*s) /* let the star eat up one character */
- s++;
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else if(*p == '?') {
- if(ISPRINT(*s)) {
- s++;
- p++;
+ if(*p == '?') {
+ if(!*s++)
+ return CURL_FNMATCH_NOMATCH;
}
- else if(*s == '\0')
- return CURL_FNMATCH_NOMATCH;
- else
- return CURL_FNMATCH_FAIL; /* cannot deal with other character */
+ else if(*p != '*')
+ break;
}
- else if(*p == '\0') {
- if(*s == '\0')
+ /* Skip string characters until we find a match with pattern suffix. */
+ for(maxstars--; *s; s++) {
+ if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH)
return CURL_FNMATCH_MATCH;
- return CURL_FNMATCH_NOMATCH;
}
- else if(*p == '\\') {
- state = CURLFNM_LOOP_BACKSLASH;
+ return CURL_FNMATCH_NOMATCH;
+ case '?':
+ if(!*s)
+ return CURL_FNMATCH_NOMATCH;
+ s++;
+ p++;
+ break;
+ case '\0':
+ return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH;
+ case '\\':
+ if(p[1])
p++;
- }
- else if(*p == '[') {
- unsigned char *pp = p + 1; /* cannot handle with pointer to register */
- if(setcharset(&pp, charset)) {
- int found = FALSE;
- if(charset[(unsigned int)*s])
- found = TRUE;
- else if(charset[CURLFNM_ALNUM])
- found = ISALNUM(*s);
- else if(charset[CURLFNM_ALPHA])
- found = ISALPHA(*s);
- else if(charset[CURLFNM_DIGIT])
- found = ISDIGIT(*s);
- else if(charset[CURLFNM_XDIGIT])
- found = ISXDIGIT(*s);
- else if(charset[CURLFNM_PRINT])
- found = ISPRINT(*s);
- else if(charset[CURLFNM_SPACE])
- found = ISSPACE(*s);
- else if(charset[CURLFNM_UPPER])
- found = ISUPPER(*s);
- else if(charset[CURLFNM_LOWER])
- found = ISLOWER(*s);
- else if(charset[CURLFNM_BLANK])
- found = ISBLANK(*s);
- else if(charset[CURLFNM_GRAPH])
- found = ISGRAPH(*s);
+ if(*s++ != *p++)
+ return CURL_FNMATCH_NOMATCH;
+ break;
+ case '[':
+ pp = p + 1; /* Copy in case of syntax error in set. */
+ if(setcharset(&pp, charset)) {
+ int found = FALSE;
+ if(!*s)
+ return CURL_FNMATCH_NOMATCH;
+ if(charset[(unsigned int)*s])
+ found = TRUE;
+ else if(charset[CURLFNM_ALNUM])
+ found = ISALNUM(*s);
+ else if(charset[CURLFNM_ALPHA])
+ found = ISALPHA(*s);
+ else if(charset[CURLFNM_DIGIT])
+ found = ISDIGIT(*s);
+ else if(charset[CURLFNM_XDIGIT])
+ found = ISXDIGIT(*s);
+ else if(charset[CURLFNM_PRINT])
+ found = ISPRINT(*s);
+ else if(charset[CURLFNM_SPACE])
+ found = ISSPACE(*s);
+ else if(charset[CURLFNM_UPPER])
+ found = ISUPPER(*s);
+ else if(charset[CURLFNM_LOWER])
+ found = ISLOWER(*s);
+ else if(charset[CURLFNM_BLANK])
+ found = ISBLANK(*s);
+ else if(charset[CURLFNM_GRAPH])
+ found = ISGRAPH(*s);
- if(charset[CURLFNM_NEGATE])
- found = !found;
+ if(charset[CURLFNM_NEGATE])
+ found = !found;
- if(found) {
- p = pp + 1;
- if(*s)
- /* don't advance if we're matching on an empty string */
- s++;
- memset(charset, 0, CURLFNM_CHSET_SIZE);
- }
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else
- return CURL_FNMATCH_FAIL;
- }
- else {
- if(*p++ != *s++)
+ if(!found)
return CURL_FNMATCH_NOMATCH;
+ p = pp + 1;
+ s++;
+ break;
}
- break;
- case CURLFNM_LOOP_BACKSLASH:
- if(ISPRINT(*p)) {
- if(*p++ == *s++)
- state = CURLFNM_LOOP_DEFAULT;
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else
- return CURL_FNMATCH_FAIL;
+
+ /* Syntax error in set: this must be taken as a regular character. */
+ /* FALLTHROUGH */
+ default:
+ if(*p++ != *s++)
+ return CURL_FNMATCH_NOMATCH;
break;
}
}
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index 83f3fa0c4..f007986c0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,6 +27,11 @@
#include "curl_gssapi.h"
#include "sendf.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02";
gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes };
static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
diff --git a/Utilities/cmcurl/lib/curl_memrchr.c b/Utilities/cmcurl/lib/curl_memrchr.c
index c521497b2..eeb3044a9 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.c
+++ b/Utilities/cmcurl/lib/curl_memrchr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,17 +44,18 @@
void *
Curl_memrchr(const void *s, int c, size_t n)
{
- const unsigned char *p = s;
- const unsigned char *q = s;
+ if(n > 0) {
+ const unsigned char *p = s;
+ const unsigned char *q = s;
- p += n - 1;
+ p += n - 1;
- while(p >= q) {
- if(*p == (unsigned char)c)
- return (void *)p;
- p--;
+ while(p >= q) {
+ if(*p == (unsigned char)c)
+ return (void *)p;
+ p--;
+ }
}
-
return NULL;
}
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index e8962769c..e27cab353 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -646,15 +646,6 @@ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
return CURLE_OK;
}
-#ifndef SIZE_T_MAX
-/* some limits.h headers have this defined, some don't */
-#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
-#define SIZE_T_MAX 18446744073709551615U
-#else
-#define SIZE_T_MAX 4294967295U
-#endif
-#endif
-
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
* (uppercase UserName + Domain) as the data
*/
@@ -754,12 +745,10 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
/* Allocate the response */
- ptr = malloc(len);
+ ptr = calloc(1, len);
if(!ptr)
return CURLE_OUT_OF_MEMORY;
- memset(ptr, 0, len);
-
/* Create the BLOB structure */
snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 03f47a3a5..353a65645 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -364,7 +364,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
case NTLMSTATE_TYPE1:
default:
/* Use Samba's 'winbind' daemon to support NTLM authentication,
- * by delegating the NTLM challenge/response protocal to a helper
+ * by delegating the NTLM challenge/response protocol to a helper
* in ntlm_auth.
* http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
* https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
diff --git a/Utilities/cmcurl/lib/curl_path.h b/Utilities/cmcurl/lib/curl_path.h
index f9d432750..5ee4ff367 100644
--- a/Utilities/cmcurl/lib/curl_path.h
+++ b/Utilities/cmcurl/lib/curl_path.h
@@ -1,3 +1,5 @@
+#ifndef HEADER_CURL_PATH_H
+#define HEADER_CURL_PATH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -5,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,3 +44,4 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
char **path);
CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
+#endif
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
new file mode 100644
index 000000000..aa3c49332
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include <curl/curl.h>
+#include "curl_range.h"
+#include "sendf.h"
+#include "strtoofft.h"
+
+/* Only include this function if one or more of FTP, FILE are enabled. */
+#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
+
+ /*
+ Check if this is a range download, and if so, set the internal variables
+ properly.
+ */
+CURLcode Curl_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+ struct Curl_easy *data = conn->data;
+
+ if(data->state.use_range && data->state.range) {
+ CURLofft from_t;
+ CURLofft to_t;
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ if(from_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ ptr++;
+ to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ if(to_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ if((to_t == CURL_OFFT_INVAL) && !from_t) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
+ from));
+ }
+ else if((from_t == CURL_OFFT_INVAL) && !to_t) {
+ /* -Y */
+ data->req.maxdownload = to;
+ data->state.resume_from = -to;
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ to));
+ }
+ else {
+ /* X-Y */
+ curl_off_t totalsize;
+
+ /* Ensure the range is sensible - to should follow from. */
+ if(from > to)
+ return CURLE_RANGE_ERROR;
+
+ totalsize = to - from;
+ if(totalsize == CURL_OFF_T_MAX)
+ return CURLE_RANGE_ERROR;
+
+ data->req.maxdownload = totalsize + 1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, to, data->req.maxdownload));
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+#endif
diff --git a/Utilities/cmcurl/lib/curl_range.h b/Utilities/cmcurl/lib/curl_range.h
new file mode 100644
index 000000000..2350df992
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_range.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_RANGE_H
+#define HEADER_CURL_RANGE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "urldata.h"
+
+CURLcode Curl_range(struct connectdata *conn);
+
+#endif /* HEADER_CURL_RANGE_H */
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 550433d67..e54e4875e 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -265,7 +265,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#if defined(USE_KERBEROS5)
+#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
@@ -333,7 +333,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
- &conn->ntlm, &resp, &len);
+ service,
+ hostname,
+ &conn->ntlm, &resp,
+ &len);
}
else
#endif
@@ -361,15 +364,6 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
conn->oauth_bearer,
&resp, &len);
}
- else if(enabledmechs & SASL_MECH_LOGIN) {
- mech = SASL_MECH_STRING_LOGIN;
- state1 = SASL_LOGIN;
- state2 = SASL_LOGIN_PASSWD;
- sasl->authused = SASL_MECH_LOGIN;
-
- if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
- }
else if(enabledmechs & SASL_MECH_PLAIN) {
mech = SASL_MECH_STRING_PLAIN;
state1 = SASL_PLAIN;
@@ -379,6 +373,15 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
&resp, &len);
}
+ else if(enabledmechs & SASL_MECH_LOGIN) {
+ mech = SASL_MECH_STRING_LOGIN;
+ state1 = SASL_LOGIN;
+ state2 = SASL_LOGIN_PASSWD;
+ sasl->authused = SASL_MECH_LOGIN;
+
+ if(force_ir || data->set.sasl_ir)
+ result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
+ }
}
if(!result && mech) {
@@ -419,13 +422,11 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
char *chlg = NULL;
size_t chlglen = 0;
#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5)
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+ defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_NTLM)
char *serverdata;
#endif
size_t len = 0;
@@ -496,6 +497,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
/* Create the type-1 message */
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
+ service, hostname,
&conn->ntlm, &resp, &len);
newstate = SASL_NTLM_TYPE2MSG;
break;
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 16e1ccdee..7e6fd5e7e 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -404,6 +404,11 @@
# define LSEEK_ERROR (off_t)-1
#endif
+#ifndef SIZEOF_TIME_T
+/* assume default size of time_t to be 32 bit */
+#define SIZEOF_TIME_T 4
+#endif
+
/*
* Default sizeof(off_t) in case it hasn't been defined in config file.
*/
@@ -439,6 +444,33 @@
#endif
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
+#if (SIZEOF_TIME_T == 4)
+# ifdef HAVE_TIME_T_UNSIGNED
+# define TIME_T_MAX UINT_MAX
+# define TIME_T_MIN 0
+# else
+# define TIME_T_MAX INT_MAX
+# define TIME_T_MIN INT_MIN
+# endif
+#else
+# ifdef HAVE_TIME_T_UNSIGNED
+# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF
+# define TIME_T_MIN 0
+# else
+# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF
+# define TIME_T_MIN (-TIME_T_MAX - 1)
+# endif
+#endif
+
+#ifndef SIZE_T_MAX
+/* some limits.h headers have this defined, some don't */
+#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
+#define SIZE_T_MAX 18446744073709551615U
+#else
+#define SIZE_T_MAX 4294967295U
+#endif
+#endif
+
/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
*/
@@ -622,11 +654,6 @@ int netware_init(void);
#error "Both libidn2 and WinIDN are enabled, choose one."
#endif
-#ifndef SIZEOF_TIME_T
-/* assume default size of time_t to be 32 bit */
-#define SIZEOF_TIME_T 4
-#endif
-
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
@@ -766,11 +793,11 @@ endings either CRLF or LF so 't' is appropriate.
# if defined(WIN32) || defined(__CYGWIN__)
# define USE_RECV_BEFORE_SEND_WORKAROUND
# endif
-#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
# ifdef USE_RECV_BEFORE_SEND_WORKAROUND
# undef USE_RECV_BEFORE_SEND_WORKAROUND
# endif
-#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
@@ -783,4 +810,9 @@ endings either CRLF or LF so 't' is appropriate.
# endif
# endif
+/* for systems that don't detect this in configure, use a sensible default */
+#ifndef CURL_SA_FAMILY_T
+#define CURL_SA_FAMILY_T unsigned short
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index a5b542c6e..6d01ea156 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -101,7 +101,6 @@
# endif
#endif
-
/*
* Definition of timeval struct for platforms that don't have it.
*/
@@ -274,25 +273,6 @@ struct timeval {
# define sfcntl fcntl
#endif
-/*
- * Uppercase macro versions of ANSI/ISO is*() functions/macros which
- * avoid negative number inputs with argument byte codes > 127.
- */
-
-#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
-#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
-#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
-#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
-#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
-#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
-#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
-#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
-#define ISLOWER(x) (islower((int) ((unsigned char)x)))
-#define ISASCII(x) (isascii((int) ((unsigned char)x)))
-
-#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
- (((unsigned char)x) == '\t'))
-
#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
@@ -347,6 +327,7 @@ struct timeval {
#define FALSE false
#endif
+#include "curl_ctype.h"
/*
* Macro WHILE_FALSE may be used to build single-iteration do-while loops,
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index edc716d0a..6b914353d 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -61,6 +61,7 @@
#include "strdup.h"
#include "progress.h"
#include "easyif.h"
+#include "multiif.h"
#include "select.h"
#include "sendf.h" /* for failf function prototype */
#include "connect.h" /* for Curl_getconnectinfo */
@@ -73,6 +74,7 @@
#include "sigpipe.h"
#include "ssh.h"
#include "setopt.h"
+#include "http_digest.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -744,6 +746,10 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(data->set.errorbuffer)
+ /* clear this as early as possible */
+ data->set.errorbuffer[0] = 0;
+
if(data->multi) {
failf(data, "easy handle already used in multi handle");
return CURLE_FAILED_INIT;
@@ -760,6 +766,9 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
data->multi_easy = multi;
}
+ if(multi->in_callback)
+ return CURLE_RECURSIVE_API_CALL;
+
/* Copy the MAXCONNECTS option to the multi handle */
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
@@ -883,6 +892,9 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* Duplicate mime data. */
result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
+ if(src->set.resolve)
+ dst->change.resolve = dst->set.resolve;
+
return result;
}
@@ -1017,6 +1029,7 @@ void curl_easy_reset(struct Curl_easy *data)
/* zero out authentication data: */
memset(&data->state.authhost, 0, sizeof(struct auth));
memset(&data->state.authproxy, 0, sizeof(struct auth));
+ Curl_digest_cleanup(data);
}
/*
@@ -1028,6 +1041,9 @@ void curl_easy_reset(struct Curl_easy *data)
* the pausing, you may get your write callback called at this point.
*
* Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
+ *
+ * NOTE: This is one of few API functions that are allowed to be called from
+ * within a callback.
*/
CURLcode curl_easy_pause(struct Curl_easy *data, int action)
{
@@ -1070,10 +1086,8 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* even if one function returns error, this loops through and frees all
buffers */
if(!result)
- result = Curl_client_chop_write(conn,
- writebuf[i].type,
- writebuf[i].buf,
- writebuf[i].len);
+ result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
+ writebuf[i].len);
free(writebuf[i].buf);
}
@@ -1092,6 +1106,10 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
+ /* This transfer may have been moved in or out of the bundle, update
+ the corresponding socket callback, if used */
+ Curl_updatesocket(data);
+
return result;
}
@@ -1132,6 +1150,9 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
ssize_t n1;
struct connectdata *c;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
result = easy_connection(data, &sfd, &c);
if(result)
return result;
@@ -1159,6 +1180,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
ssize_t n1;
struct connectdata *c = NULL;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
result = easy_connection(data, &sfd, &c);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 0bbc0e180..db04cc2da 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,6 +61,7 @@
#include "url.h"
#include "parsedate.h" /* for the week day and month names */
#include "warnless.h"
+#include "curl_range.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -125,65 +126,6 @@ static CURLcode file_setup_connection(struct connectdata *conn)
return CURLE_OK;
}
- /*
- Check if this is a range download, and if so, set the internal variables
- properly. This code is copied from the FTP implementation and might as
- well be factored out.
- */
-static CURLcode file_range(struct connectdata *conn)
-{
- curl_off_t from, to;
- curl_off_t totalsize = -1;
- char *ptr;
- char *ptr2;
- struct Curl_easy *data = conn->data;
-
- if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
- if(to_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
- /* X - */
- data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
- from));
- }
- else if((from_t == CURL_OFFT_INVAL) && !to_t) {
- /* -Y */
- data->req.maxdownload = to;
- data->state.resume_from = -to;
- DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- to));
- }
- else {
- /* X-Y */
- totalsize = to-from;
- if(totalsize == CURL_OFF_T_MAX)
- /* this is too big to increase, so bail out */
- return CURLE_RANGE_ERROR;
- data->req.maxdownload = totalsize + 1; /* include last byte */
- data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
- " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, data->req.maxdownload));
- }
- DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
- " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, to, data->req.maxdownload));
- }
- else
- data->req.maxdownload = -1;
- return CURLE_OK;
-}
-
/*
* file_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. We emulate a
@@ -461,12 +403,12 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
/* we could stat it, then read out the size */
expected_size = statbuf.st_size;
/* and store the modification time */
- data->info.filetime = (long)statbuf.st_mtime;
+ data->info.filetime = statbuf.st_mtime;
fstated = TRUE;
}
if(fstated && !data->state.range && data->set.timecondition) {
- if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) {
+ if(!Curl_meets_timecondition(data, data->info.filetime)) {
*done = TRUE;
return CURLE_OK;
}
@@ -514,7 +456,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
}
/* Check whether file range has been specified */
- file_range(conn);
+ result = Curl_range(conn);
+ if(result)
+ return result;
/* Adjust the start offset in case we want to get the N last bytes
* of the stream iff the filesize could be determined */
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index 387298847..4e72e1eba 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,14 +33,11 @@ struct fileinfo *Curl_fileinfo_alloc(void)
return calloc(1, sizeof(struct fileinfo));
}
-void Curl_fileinfo_dtor(void *user, void *element)
+void Curl_fileinfo_cleanup(struct fileinfo *finfo)
{
- struct fileinfo *finfo = element;
- (void) user;
if(!finfo)
return;
Curl_safefree(finfo->info.b_data);
-
free(finfo);
}
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index c5d0ee5b6..f4d8f3b90 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,6 @@ struct fileinfo {
};
struct fileinfo *Curl_fileinfo_alloc(void);
-
-void Curl_fileinfo_dtor(void *, void *);
+void Curl_fileinfo_cleanup(struct fileinfo *finfo);
#endif /* HEADER_CURL_FILEINFO_H */
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index d0579c52f..f91241052 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -155,60 +155,6 @@ static FormInfo * AddFormInfo(char *value,
/***************************************************************************
*
- * ContentTypeForFilename()
- *
- * Provides content type for filename if one of the known types (else
- * (either the prevtype or the default is returned).
- *
- * Returns some valid contenttype for filename.
- *
- ***************************************************************************/
-static const char *ContentTypeForFilename(const char *filename,
- const char *prevtype)
-{
- const char *contenttype = NULL;
- unsigned int i;
- /*
- * No type was specified, we scan through a few well-known
- * extensions and pick the first we match!
- */
- struct ContentType {
- const char *extension;
- const char *type;
- };
- static const struct ContentType ctts[]={
- {".gif", "image/gif"},
- {".jpg", "image/jpeg"},
- {".jpeg", "image/jpeg"},
- {".txt", "text/plain"},
- {".html", "text/html"},
- {".xml", "application/xml"}
- };
-
- if(prevtype)
- /* default to the previously set/used! */
- contenttype = prevtype;
- else
- contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
-
- if(filename) { /* in case a NULL was passed in */
- for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
- if(strlen(filename) >= strlen(ctts[i].extension)) {
- if(strcasecompare(filename +
- strlen(filename) - strlen(ctts[i].extension),
- ctts[i].extension)) {
- contenttype = ctts[i].type;
- break;
- }
- }
- }
- }
- /* we have a contenttype by now */
- return contenttype;
-}
-
-/***************************************************************************
- *
* FormAdd()
*
* Stores a formpost parameter and builds the appropriate linked list.
@@ -627,9 +573,15 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
!form->contenttype) {
char *f = form->flags & HTTPPOST_BUFFER?
form->showfilename : form->value;
+ char const *type;
+ type = Curl_mime_contenttype(f);
+ if(!type)
+ type = prevtype;
+ if(!type)
+ type = FILE_CONTENTTYPE_DEFAULT;
/* our contenttype is missing */
- form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
+ form->contenttype = strdup(type);
if(!form->contenttype) {
return_value = CURL_FORMADD_MEMORY;
break;
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index d3b02201f..a42c0c7c6 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -59,6 +59,7 @@
#include "ftp.h"
#include "fileinfo.h"
#include "ftplistparser.h"
+#include "curl_range.h"
#include "curl_sec.h"
#include "strtoofft.h"
#include "strcase.h"
@@ -310,9 +311,11 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
int error = 0;
/* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
error = data->set.fsockopt(data->set.sockopt_client,
s,
CURLSOCKTYPE_ACCEPT);
+ Curl_set_in_callback(data, false);
if(error) {
close_secondarysocket(conn);
@@ -1471,7 +1474,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
slashPos = strrchr(inpath, '/');
n = slashPos - inpath;
}
- result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
+ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE);
if(result)
return result;
}
@@ -1535,7 +1538,7 @@ static CURLcode ftp_state_type(struct connectdata *conn)
date. */
if(data->set.opt_no_body && ftpc->file &&
ftp_need_type(conn, data->set.prefer_ascii)) {
- /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
+ /* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
size! */
@@ -1615,8 +1618,10 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -1783,7 +1788,7 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- if(conn->bits.ipv6) {
+ if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
failf(conn->data, "Failed EPSV attempt, exiting\n");
return CURLE_WEIRD_SERVER_REPLY;
@@ -1905,13 +1910,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
if(data->set.ftp_skip_ip) {
/* told to ignore the remotely given IP but instead use the host we used
for the control connection */
- infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n",
+ infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n",
ip[0], ip[1], ip[2], ip[3],
conn->host.name);
ftpc->newhost = strdup(control_address(conn));
}
else
- ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
if(!ftpc->newhost)
return CURLE_OUT_OF_MEMORY;
@@ -2060,7 +2065,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
"%04d%02d%02d %02d:%02d:%02d GMT",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
- data->info.filetime = (long)curl_getdate(timebuf, &secs);
+ data->info.filetime = curl_getdate(timebuf, &secs);
}
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2072,7 +2077,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
char headerbuf[128];
- time_t filetime = (time_t)data->info.filetime;
+ time_t filetime = data->info.filetime;
struct tm buffer;
const struct tm *tm = &buffer;
@@ -3180,14 +3185,16 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(data->state.wildcardmatch) {
if(data->set.chunk_end && ftpc->file) {
+ Curl_set_in_callback(data, true);
data->set.chunk_end(data->wildcard.customptr);
+ Curl_set_in_callback(data, false);
}
ftpc->known_filesize = -1;
}
if(!result)
/* get the "raw" path */
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
@@ -3463,62 +3470,6 @@ ftp_pasv_verbose(struct connectdata *conn,
#endif
/*
- Check if this is a range download, and if so, set the internal variables
- properly.
- */
-
-static CURLcode ftp_range(struct connectdata *conn)
-{
- curl_off_t from, to;
- char *ptr;
- struct Curl_easy *data = conn->data;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-
- if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, NULL, 0, &to);
- if(to_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
- /* X - */
- data->state.resume_from = from;
- DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
- " to end of file\n", from));
- }
- else if(!to_t && (from_t == CURL_OFFT_INVAL)) {
- /* -Y */
- data->req.maxdownload = to;
- data->state.resume_from = -to;
- DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
- " bytes\n", to));
- }
- else {
- /* X-Y */
- data->req.maxdownload = (to - from) + 1; /* include last byte */
- data->state.resume_from = from;
- DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
- " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, data->req.maxdownload));
- }
- DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T
- " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, to, data->req.maxdownload));
- ftpc->dont_check = TRUE; /* don't check for successful transfer */
- }
- else
- data->req.maxdownload = -1;
- return CURLE_OK;
-}
-
-
-/*
* ftp_do_more()
*
* This function shall be called when the second FTP (data) connection is
@@ -3640,7 +3591,13 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* download */
ftp->downloadsize = -1; /* unknown as of yet */
- result = ftp_range(conn);
+ result = Curl_range(conn);
+
+ if(result == CURLE_OK && data->req.maxdownload >= 0) {
+ /* Don't check for successful transfer */
+ ftpc->dont_check = TRUE;
+ }
+
if(result)
;
else if(data->set.ftp_list_only || !ftpc->file) {
@@ -3731,10 +3688,10 @@ CURLcode ftp_perform(struct connectdata *conn,
static void wc_data_dtor(void *ptr)
{
- struct ftp_wc_tmpdata *tmp = ptr;
- if(tmp)
- Curl_ftp_parselist_data_free(&tmp->parser);
- free(tmp);
+ struct ftp_wc *ftpwc = ptr;
+ if(ftpwc && ftpwc->parser)
+ Curl_ftp_parselist_data_free(&ftpwc->parser);
+ free(ftpwc);
}
static CURLcode init_wc_data(struct connectdata *conn)
@@ -3743,7 +3700,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
char *path = conn->data->state.path;
struct WildcardData *wildcard = &(conn->data->wildcard);
CURLcode result = CURLE_OK;
- struct ftp_wc_tmpdata *ftp_tmp;
+ struct ftp_wc *ftpwc = NULL;
last_slash = strrchr(conn->data->state.path, '/');
if(last_slash) {
@@ -3775,23 +3732,22 @@ static CURLcode init_wc_data(struct connectdata *conn)
/* program continues only if URL is not ending with slash, allocate needed
resources for wildcard transfer */
- /* allocate ftp protocol specific temporary wildcard data */
- ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata));
- if(!ftp_tmp) {
- Curl_safefree(wildcard->pattern);
- return CURLE_OUT_OF_MEMORY;
+ /* allocate ftp protocol specific wildcard data */
+ ftpwc = calloc(1, sizeof(struct ftp_wc));
+ if(!ftpwc) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
/* INITIALIZE parselist structure */
- ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
- if(!ftp_tmp->parser) {
- Curl_safefree(wildcard->pattern);
- free(ftp_tmp);
- return CURLE_OUT_OF_MEMORY;
+ ftpwc->parser = Curl_ftp_parselist_data_alloc();
+ if(!ftpwc->parser) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
- wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
- wildcard->tmp_dtor = wc_data_dtor;
+ wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
+ wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
@@ -3800,33 +3756,36 @@ static CURLcode init_wc_data(struct connectdata *conn)
/* try to parse ftp url */
result = ftp_parse_url_path(conn);
if(result) {
- Curl_safefree(wildcard->pattern);
- wildcard->tmp_dtor(wildcard->tmp);
- wildcard->tmp_dtor = ZERO_NULL;
- wildcard->tmp = NULL;
- return result;
+ goto fail;
}
wildcard->path = strdup(conn->data->state.path);
if(!wildcard->path) {
- Curl_safefree(wildcard->pattern);
- wildcard->tmp_dtor(wildcard->tmp);
- wildcard->tmp_dtor = ZERO_NULL;
- wildcard->tmp = NULL;
- return CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
/* backup old write_function */
- ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
+ ftpwc->backup.write_function = conn->data->set.fwrite_func;
/* parsing write function */
conn->data->set.fwrite_func = Curl_ftp_parselist;
/* backup old file descriptor */
- ftp_tmp->backup.file_descriptor = conn->data->set.out;
+ ftpwc->backup.file_descriptor = conn->data->set.out;
/* let the writefunc callback know what curl pointer is working with */
conn->data->set.out = conn;
infof(conn->data, "Wildcard - Parsing started\n");
return CURLE_OK;
+
+ fail:
+ if(ftpwc) {
+ Curl_ftp_parselist_data_free(&ftpwc->parser);
+ free(ftpwc);
+ }
+ Curl_safefree(wildcard->pattern);
+ wildcard->dtor = ZERO_NULL;
+ wildcard->protdata = NULL;
+ return result;
}
/* This is called recursively */
@@ -3847,14 +3806,14 @@ static CURLcode wc_statemach(struct connectdata *conn)
case CURLWC_MATCHING: {
/* In this state is LIST response successfully parsed, so lets restore
previous WRITEFUNCTION callback and WRITEDATA pointer */
- struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
- conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
- conn->data->set.out = ftp_tmp->backup.file_descriptor;
- ftp_tmp->backup.write_function = ZERO_NULL;
- ftp_tmp->backup.file_descriptor = NULL;
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ conn->data->set.fwrite_func = ftpwc->backup.write_function;
+ conn->data->set.out = ftpwc->backup.file_descriptor;
+ ftpwc->backup.write_function = ZERO_NULL;
+ ftpwc->backup.file_descriptor = NULL;
wildcard->state = CURLWC_DOWNLOADING;
- if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
+ if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
/* error found in LIST parsing */
wildcard->state = CURLWC_CLEAN;
return wc_statemach(conn);
@@ -3884,8 +3843,11 @@ static CURLcode wc_statemach(struct connectdata *conn)
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) {
- long userresponse = conn->data->set.chunk_bgn(
+ long userresponse;
+ Curl_set_in_callback(conn->data, true);
+ userresponse = conn->data->set.chunk_bgn(
finfo, wildcard->customptr, (int)wildcard->filelist.size);
+ Curl_set_in_callback(conn->data, false);
switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP:
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
@@ -3921,8 +3883,11 @@ static CURLcode wc_statemach(struct connectdata *conn)
} break;
case CURLWC_SKIP: {
- if(conn->data->set.chunk_end)
+ if(conn->data->set.chunk_end) {
+ Curl_set_in_callback(conn->data, true);
conn->data->set.chunk_end(conn->data->wildcard.customptr);
+ Curl_set_in_callback(conn->data, false);
+ }
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
wildcard->state = (wildcard->filelist.size == 0) ?
CURLWC_CLEAN : CURLWC_DOWNLOADING;
@@ -3930,10 +3895,10 @@ static CURLcode wc_statemach(struct connectdata *conn)
}
case CURLWC_CLEAN: {
- struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ struct ftp_wc *ftpwc = wildcard->protdata;
result = CURLE_OK;
- if(ftp_tmp)
- result = Curl_ftp_parselist_geterror(ftp_tmp->parser);
+ if(ftpwc)
+ result = Curl_ftp_parselist_geterror(ftpwc->parser);
wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
} break;
@@ -3941,6 +3906,8 @@ static CURLcode wc_statemach(struct connectdata *conn)
case CURLWC_DONE:
case CURLWC_ERROR:
case CURLWC_CLEAR:
+ if(wildcard->dtor)
+ wildcard->dtor(wildcard->protdata);
break;
}
@@ -4193,7 +4160,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? dirlen : 1,
&ftpc->dirs[0], NULL,
- FALSE);
+ TRUE);
if(result) {
freedirs(ftpc);
return result;
@@ -4300,7 +4267,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
size_t dlen;
char *path;
CURLcode result =
- Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, TRUE);
if(result) {
freedirs(ftpc);
return result;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index e4aa63f17..7ec339118 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -81,7 +81,7 @@ typedef enum {
struct ftp_parselist_data; /* defined later in ftplistparser.c */
-struct ftp_wc_tmpdata {
+struct ftp_wc {
struct ftp_parselist_data *parser;
struct {
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index 262ac0306..249fe09c8 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,6 +49,7 @@
#include "ftplistparser.h"
#include "curl_fnmatch.h"
#include "curl_memory.h"
+#include "multiif.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -184,10 +185,13 @@ struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
}
-void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
+void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp)
{
- free(*pl_data);
- *pl_data = NULL;
+ struct ftp_parselist_data *parser = *parserp;
+ if(parser)
+ Curl_fileinfo_cleanup(parser->file_data);
+ free(parser);
+ *parserp = NULL;
}
@@ -269,9 +273,9 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
{
curl_fnmatch_callback compare;
struct WildcardData *wc = &conn->data->wildcard;
- struct ftp_wc_tmpdata *tmpdata = wc->tmp;
+ struct ftp_wc *ftpwc = wc->protdata;
struct curl_llist *llist = &wc->filelist;
- struct ftp_parselist_data *parser = tmpdata->parser;
+ struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
struct curl_fileinfo *finfo = &infop->info;
@@ -294,6 +298,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
+ Curl_set_in_callback(conn->data, true);
if(compare(conn->data->set.fnmatch_data, wc->pattern,
finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
@@ -305,15 +310,16 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
else {
add = FALSE;
}
+ Curl_set_in_callback(conn->data, false);
if(add) {
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
}
else {
- Curl_fileinfo_dtor(NULL, finfo);
+ Curl_fileinfo_cleanup(infop);
}
- tmpdata->parser->file_data = NULL;
+ ftpwc->parser->file_data = NULL;
return CURLE_OK;
}
@@ -322,8 +328,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
{
size_t bufflen = size*nmemb;
struct connectdata *conn = (struct connectdata *)connptr;
- struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
- struct ftp_parselist_data *parser = tmpdata->parser;
+ struct ftp_wc *ftpwc = conn->data->wildcard.protdata;
+ struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;
unsigned long i = 0;
@@ -378,7 +384,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data = tmp;
}
else {
- Curl_fileinfo_dtor(NULL, parser->file_data);
+ Curl_fileinfo_cleanup(parser->file_data);
parser->file_data = NULL;
parser->error = CURLE_OUT_OF_MEMORY;
goto fail;
@@ -1000,12 +1006,13 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
i++;
}
+ return retsize;
fail:
/* Clean up any allocated memory. */
if(parser->file_data) {
- Curl_fileinfo_dtor(NULL, parser->file_data);
+ Curl_fileinfo_cleanup(parser->file_data);
parser->file_data = NULL;
}
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 862ced019..d280eebfa 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -156,7 +156,12 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
*param_longp = data->info.httpproxycode;
break;
case CURLINFO_FILETIME:
- *param_longp = data->info.filetime;
+ if(data->info.filetime > LONG_MAX)
+ *param_longp = LONG_MAX;
+ else if(data->info.filetime < LONG_MIN)
+ *param_longp = LONG_MIN;
+ else
+ *param_longp = (long)data->info.filetime;
break;
case CURLINFO_HEADER_SIZE:
*param_longp = data->info.header_size;
@@ -253,6 +258,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
curl_off_t *param_offt)
{
switch(info) {
+ case CURLINFO_FILETIME_T:
+ *param_offt = (curl_off_t)data->info.filetime;
+ break;
case CURLINFO_SIZE_UPLOAD_T:
*param_offt = data->progress.uploaded;
break;
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index c99b1b699..15a128fec 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -261,11 +261,11 @@ size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num)
{
const char *key_str = (const char *) key;
const char *end = key_str + key_length;
- unsigned long h = 5381;
+ size_t h = 5381;
while(key_str < end) {
h += h << 5;
- h ^= (unsigned long) *key_str++;
+ h ^= *key_str++;
}
return (h % slots_num);
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index 37bcc12c1..c9d8112d8 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -25,7 +25,7 @@
#if defined(USE_OPENSSL) \
|| defined(USE_AXTLS) \
|| defined(USE_GSKIT) \
- || (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
+ || defined(USE_SCHANNEL)
/* these backends use functions from this file */
#ifdef HAVE_NETINET_IN_H
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 886aeec42..c2f9defd9 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,10 +54,12 @@
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
+#include "rand.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_ntop.h"
+#include "multiif.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -366,6 +368,70 @@ Curl_fetch_addr(struct connectdata *conn,
}
/*
+ * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
+ * struct by re-linking its linked list.
+ *
+ * The addr argument should be the address of a pointer to the head node of a
+ * `Curl_addrinfo` list and it will be modified to point to the new head after
+ * shuffling.
+ *
+ * Not declared static only to make it easy to use in a unit test!
+ *
+ * @unittest: 1608
+ */
+CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
+{
+ CURLcode result = CURLE_OK;
+ const int num_addrs = Curl_num_addresses(*addr);
+
+ if(num_addrs > 1) {
+ Curl_addrinfo **nodes;
+ infof(data, "Shuffling %i addresses", num_addrs);
+
+ nodes = malloc(num_addrs*sizeof(*nodes));
+ if(nodes) {
+ int i;
+ unsigned int *rnd;
+ const size_t rnd_size = num_addrs * sizeof(*rnd);
+
+ /* build a plain array of Curl_addrinfo pointers */
+ nodes[0] = *addr;
+ for(i = 1; i < num_addrs; i++) {
+ nodes[i] = nodes[i-1]->ai_next;
+ }
+
+ rnd = malloc(rnd_size);
+ if(rnd) {
+ /* Fisher-Yates shuffle */
+ if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
+ Curl_addrinfo *swap_tmp;
+ for(i = num_addrs - 1; i > 0; i--) {
+ swap_tmp = nodes[rnd[i] % (i + 1)];
+ nodes[rnd[i] % (i + 1)] = nodes[i];
+ nodes[i] = swap_tmp;
+ }
+
+ /* relink list in the new order */
+ for(i = 1; i < num_addrs; i++) {
+ nodes[i-1]->ai_next = nodes[i];
+ }
+
+ nodes[num_addrs-1]->ai_next = NULL;
+ *addr = nodes[0];
+ }
+ free(rnd);
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(nodes);
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ return result;
+}
+
+/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
* When calling Curl_resolv() has resulted in a response with a returned
@@ -385,6 +451,13 @@ Curl_cache_addr(struct Curl_easy *data,
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
+ /* shuffle addresses if requested */
+ if(data->set.dns_shuffle_addresses) {
+ CURLcode result = Curl_shuffle_addr(data, &addr);
+ if(!result)
+ return NULL;
+ }
+
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
@@ -481,6 +554,17 @@ int Curl_resolv(struct connectdata *conn,
if(!Curl_ipvalid(conn))
return CURLRESOLV_ERROR;
+ /* notify the resolver start callback */
+ if(data->set.resolver_start) {
+ int st;
+ Curl_set_in_callback(data, true);
+ st = data->set.resolver_start(data->state.resolver, NULL,
+ data->set.resolver_start_client);
+ Curl_set_in_callback(data, false);
+ if(st)
+ return CURLRESOLV_ERROR;
+ }
+
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to the
resolve call */
@@ -781,7 +865,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
struct curl_slist *hostp;
char hostname[256];
- int port;
+ int port = 0;
for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
if(!hostp->data)
@@ -819,32 +903,95 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
}
else {
struct Curl_dns_entry *dns;
- Curl_addrinfo *addr;
+ Curl_addrinfo *head = NULL, *tail = NULL;
char *entry_id;
size_t entry_len;
- char buffer[256];
- char *address = &buffer[0];
+ char address[64];
+ char *addresses = NULL;
+ char *addr_begin;
+ char *addr_end;
+ char *port_ptr;
+ char *end_ptr;
+ char *host_end;
+ unsigned long tmp_port;
+ bool error = true;
+
+ host_end = strchr(hostp->data, ':');
+ if(!host_end ||
+ ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
+ goto err;
+
+ memcpy(hostname, hostp->data, host_end - hostp->data);
+ hostname[host_end - hostp->data] = '\0';
+
+ port_ptr = host_end + 1;
+ tmp_port = strtoul(port_ptr, &end_ptr, 10);
+ if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
+ goto err;
+
+ port = (int)tmp_port;
+ addresses = end_ptr + 1;
+
+ while(*end_ptr) {
+ size_t alen;
+ Curl_addrinfo *ai;
+
+ addr_begin = end_ptr + 1;
+ addr_end = strchr(addr_begin, ',');
+ if(!addr_end)
+ addr_end = addr_begin + strlen(addr_begin);
+ end_ptr = addr_end;
+
+ /* allow IP(v6) address within [brackets] */
+ if(*addr_begin == '[') {
+ if(addr_end == addr_begin || *(addr_end - 1) != ']')
+ goto err;
+ ++addr_begin;
+ --addr_end;
+ }
- if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
- address)) {
- infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
- hostp->data);
- continue;
- }
+ alen = addr_end - addr_begin;
+ if(!alen)
+ continue;
+
+ if(alen >= sizeof(address))
+ goto err;
- /* allow IP(v6) address within [brackets] */
- if(address[0] == '[') {
- size_t alen = strlen(address);
- if(address[alen-1] != ']')
- /* it needs to also end with ] to be valid */
+ memcpy(address, addr_begin, alen);
+ address[alen] = '\0';
+
+#ifndef ENABLE_IPV6
+ if(strchr(address, ':')) {
+ infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n",
+ address);
continue;
- address[alen-1] = 0; /* zero terminate there */
- address++; /* pass the open bracket */
+ }
+#endif
+
+ ai = Curl_str2addr(address, port);
+ if(!ai) {
+ infof(data, "Resolve address '%s' found illegal!\n", address);
+ goto err;
+ }
+
+ if(tail) {
+ tail->ai_next = ai;
+ tail = tail->ai_next;
+ }
+ else {
+ head = tail = ai;
+ }
}
- addr = Curl_str2addr(address, port);
- if(!addr) {
- infof(data, "Address in '%s' found illegal!\n", hostp->data);
+ if(!head)
+ goto err;
+
+ error = false;
+ err:
+ if(error) {
+ infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
+ hostp->data);
+ Curl_freeaddrinfo(head);
continue;
}
@@ -852,10 +999,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!entry_id) {
- Curl_freeaddrinfo(addr);
+ Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
-
entry_len = strlen(entry_id);
if(data->share)
@@ -869,7 +1015,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(!dns) {
/* if not in the cache already, put this host in the cache */
- dns = Curl_cache_addr(data, addr, hostname, port);
+ dns = Curl_cache_addr(data, head, hostname, port);
if(dns) {
dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
/* release the returned reference; the cache itself will keep the
@@ -880,19 +1026,19 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
else {
/* this is a duplicate, free it again */
infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
- hostname, port, address);
- Curl_freeaddrinfo(addr);
+ hostname, port, addresses);
+ Curl_freeaddrinfo(head);
}
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns) {
- Curl_freeaddrinfo(addr);
+ Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
infof(data, "Added %s:%d:%s to DNS cache\n",
- hostname, port, address);
+ hostname, port, addresses);
}
}
data->change.resolve = NULL; /* dealt with now */
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 298eeeee3..1de4bee8d 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -182,6 +182,17 @@ struct Curl_dns_entry *
Curl_fetch_addr(struct connectdata *conn,
const char *hostname,
int port);
+
+/*
+ * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
+ * struct by re-linking its linked list.
+ *
+ * The addr argument should be the address of a pointer to the head node of a
+ * `Curl_addrinfo` list and it will be modified to point to the new head after
+ * shuffling.
+ */
+CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr);
+
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index a5007670d..ff1d6813a 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -92,6 +92,8 @@ static int http_getsock_do(struct connectdata *conn,
int numsocks);
static int http_should_fail(struct connectdata *conn);
+static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+
#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done);
static int https_getsock(struct connectdata *conn,
@@ -177,9 +179,9 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
* if proxy headers are not available, then it will lookup into http header
* link list
*
- * It takes a connectdata struct as input instead of the Curl_easy simply
- * to know if this is a proxy request or not, as it then might check a
- * different header list.
+ * It takes a connectdata struct as input instead of the Curl_easy simply to
+ * know if this is a proxy request or not, as it then might check a different
+ * header list. Provide the header prefix without colon!.
*/
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader)
@@ -191,7 +193,8 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
head; head = head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen) &&
+ Curl_headersep(head->data[thislen]))
return head->data;
}
@@ -211,8 +214,6 @@ char *Curl_copy_header_value(const char *header)
char *value;
size_t len;
- DEBUGASSERT(header);
-
/* Find the end of the header name */
while(*header && (*header != ':'))
++header;
@@ -432,7 +433,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
data left to send, keep on sending. */
/* rewind data when completely done sending! */
- if(!conn->bits.authneg) {
+ if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
infof(data, "Rewind stream after send\n");
}
@@ -614,9 +615,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */
if((proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
+ !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
(!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization:"))) {
+ !Curl_checkheaders(conn, "Authorization"))) {
auth = "Basic";
result = http_output_basic(conn, proxy);
if(result)
@@ -1357,6 +1358,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
+ if(conn->data->set.haproxyprotocol) {
+ /* add HAProxy PROXY protocol header */
+ result = add_haproxy_protocol_header(conn);
+ if(result)
+ return result;
+ }
+
if(conn->given->protocol & CURLPROTO_HTTPS) {
/* perform SSL initialization */
result = https_connecting(conn, done);
@@ -1382,6 +1390,47 @@ static int http_getsock_do(struct connectdata *conn,
return GETSOCK_WRITESOCK(0);
}
+static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
+{
+ char proxy_header[128];
+ Curl_send_buffer *req_buffer;
+ CURLcode result;
+ char tcp_version[5];
+
+ /* Emit the correct prefix for IPv6 */
+ if(conn->bits.ipv6) {
+ strcpy(tcp_version, "TCP6");
+ }
+ else {
+ strcpy(tcp_version, "TCP4");
+ }
+
+ snprintf(proxy_header,
+ sizeof proxy_header,
+ "PROXY %s %s %s %li %li\r\n",
+ tcp_version,
+ conn->data->info.conn_local_ip,
+ conn->data->info.conn_primary_ip,
+ conn->data->info.conn_local_port,
+ conn->data->info.conn_primary_port);
+
+ req_buffer = Curl_add_buffer_init();
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_add_bufferf(req_buffer, proxy_header);
+ if(result)
+ return result;
+
+ result = Curl_add_buffer_send(req_buffer,
+ conn,
+ &conn->data->info.request_size,
+ 0,
+ FIRSTSOCKET);
+
+ return result;
+}
+
#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done)
{
@@ -1533,7 +1582,7 @@ static CURLcode expect100(struct Curl_easy *data,
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1598,7 +1647,32 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
headers = h[i];
while(headers) {
+ char *semicolonp = NULL;
ptr = strchr(headers->data, ':');
+ if(!ptr) {
+ char *optr;
+ /* no colon, semicolon? */
+ ptr = strchr(headers->data, ';');
+ if(ptr) {
+ optr = ptr;
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* this may be used for something else in the future */
+ optr = NULL;
+ }
+ else {
+ if(*(--ptr) == ';') {
+ /* send no-value custom header if terminated by semicolon */
+ *ptr = ':';
+ semicolonp = ptr;
+ }
+ }
+ ptr = optr;
+ }
+ }
if(ptr) {
/* we require a colon for this to be a true header */
@@ -1606,8 +1680,9 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
while(*ptr && ISSPACE(*ptr))
ptr++;
- if(*ptr) {
- /* only send this if the contents was non-blank */
+ if(*ptr || semicolonp) {
+ /* only send this if the contents was non-blank or done special */
+ CURLcode result = CURLE_OK;
if(conn->allocptr.host &&
/* a Host: header was sent already, don't pass on any custom Host:
@@ -1645,40 +1720,12 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
- CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
- headers->data);
- if(result)
- return result;
- }
- }
- }
- else {
- ptr = strchr(headers->data, ';');
- if(ptr) {
-
- ptr++; /* pass the semicolon */
- while(*ptr && ISSPACE(*ptr))
- ptr++;
-
- if(*ptr) {
- /* this may be used for something else in the future */
- }
- else {
- if(*(--ptr) == ';') {
- CURLcode result;
-
- /* send no-value custom header if terminated by semicolon */
- *ptr = ':';
- result = Curl_add_bufferf(req_buffer, "%s\r\n",
- headers->data);
-
- /* restore the previous value */
- *ptr = ';';
-
- if(result)
- return result;
- }
+ result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
}
+ if(semicolonp)
+ *semicolonp = ';'; /* put back the semicolon */
+ if(result)
+ return result;
}
}
headers = headers->next;
@@ -1869,7 +1916,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:")) {
+ if(Curl_checkheaders(conn, "User-Agent")) {
free(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
@@ -1890,7 +1937,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->bits.authneg = FALSE;
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
if(!conn->allocptr.ref)
return CURLE_OUT_OF_MEMORY;
@@ -1899,11 +1946,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref = NULL;
#if !defined(CURL_DISABLE_COOKIES)
- if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
addcookies = data->set.str[STRING_COOKIE];
#endif
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
@@ -1919,22 +1966,29 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
- if(!Curl_checkheaders(conn, "TE:") &&
+ if(!Curl_checkheaders(conn, "TE") &&
data->set.http_transfer_encoding) {
/* When we are to insert a TE: header in the request, we must also insert
TE in a Connection: header, so we need to merge the custom provided
Connection: header and prevent the original to get sent. Note that if
the user has inserted his/hers own TE: header we don't do this magic
but then assume that the user will handle it all! */
- char *cptr = Curl_checkheaders(conn, "Connection:");
+ char *cptr = Curl_checkheaders(conn, "Connection");
#define TE_HEADER "TE: gzip\r\n"
Curl_safefree(conn->allocptr.te);
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
/* Create the (updated) Connection: header */
- conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
- strdup("Connection: TE\r\n" TE_HEADER);
+ conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+ free(cptr);
if(!conn->allocptr.te)
return CURLE_OUT_OF_MEMORY;
}
@@ -1958,7 +2012,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(http->sendit) {
- const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
+ const char *cthdr = Curl_checkheaders(conn, "Content-Type");
/* Read and seek body only. */
http->sendit->flags |= MIME_BODY_ONLY;
@@ -1982,7 +2036,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->postsize = Curl_mime_size(http->sendit);
}
- ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky =
@@ -2016,7 +2070,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_safefree(conn->allocptr.host);
- ptr = Curl_checkheaders(conn, "Host:");
+ ptr = Curl_checkheaders(conn, "Host");
if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
@@ -2055,7 +2109,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#endif
if(strcmp("Host:", ptr)) {
- conn->allocptr.host = aprintf("%s\r\n", ptr);
+ conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]);
if(!conn->allocptr.host)
return CURLE_OUT_OF_MEMORY;
}
@@ -2078,7 +2132,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
host,
conn->bits.ipv6_ip?"]":"");
else
- conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
+ conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
conn->bits.ipv6_ip?"[":"",
host,
conn->bits.ipv6_ip?"]":"",
@@ -2164,7 +2218,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif /* CURL_DISABLE_PROXY */
- http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
+ http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
data->state.resume_from) {
@@ -2191,8 +2245,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Now, let's read off the proper amount of bytes from the
input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -2243,14 +2299,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* ones if any such are specified.
*/
if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
- !Curl_checkheaders(conn, "Range:")) {
+ !Curl_checkheaders(conn, "Range")) {
/* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range);
}
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
- !Curl_checkheaders(conn, "Content-Range:")) {
+ !Curl_checkheaders(conn, "Content-Range")) {
/* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline);
@@ -2352,7 +2408,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref:"" /* Referer: <data> */,
(conn->bits.httpproxy &&
!conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
"Proxy-Connection: Keep-Alive\r\n":"",
te
);
@@ -2453,7 +2509,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
postsize = data->state.infilesize;
if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
@@ -2515,7 +2571,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(postsize != -1 && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
@@ -2540,7 +2596,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -2594,7 +2650,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
@@ -2604,7 +2660,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/"
"x-www-form-urlencoded\r\n");
@@ -2616,7 +2672,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -2878,20 +2934,19 @@ static CURLcode header_append(struct Curl_easy *data,
struct SingleRequest *k,
size_t length)
{
- if(k->hbuflen + length >= data->state.headersize) {
+ size_t newsize = k->hbuflen + length;
+ if(newsize > CURL_MAX_HTTP_HEADER) {
+ /* The reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause
+ reallocs infinitely */
+ failf(data, "Rejected %zd bytes header (max is %d)!", newsize,
+ CURL_MAX_HTTP_HEADER);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(newsize >= data->state.headersize) {
/* We enlarge the header buffer as it is too small */
char *newbuff;
size_t hbufp_index;
- size_t newsize;
-
- if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
- /* The reason to have a max limit for this is to avoid the risk of a bad
- server feeding libcurl with a never-ending header that will cause
- reallocs infinitely */
- failf(data, "Avoided giant realloc for header (max is %d)!",
- CURL_MAX_HTTP_HEADER);
- return CURLE_OUT_OF_MEMORY;
- }
newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2);
hbufp_index = k->hbufp - data->state.headerbuff;
@@ -2959,6 +3014,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
{
CURLcode result;
struct SingleRequest *k = &data->req;
+ ssize_t onread = *nread;
+ char *ostr = k->str;
/* header line within buffer loop */
do {
@@ -3023,7 +3080,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else {
/* this was all we read so it's all a bad header */
k->badheader = HEADER_ALLBAD;
- *nread = (ssize_t)rest_length;
+ *nread = onread;
+ k->str = ostr;
+ return CURLE_OK;
}
break;
}
@@ -3677,7 +3736,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_add(data,
- data->cookies, TRUE, k->p + 11,
+ data->cookies, TRUE, FALSE, k->p + 11,
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
conn->allocptr.cookiehost?
@@ -3692,7 +3751,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"),
&secs);
if(data->set.get_filetime)
- data->info.filetime = (long)k->timeofdoc;
+ data->info.filetime = k->timeofdoc;
}
else if((checkprefix("WWW-Authenticate:", k->p) &&
(401 == k->httpcode)) ||
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index d2781bc0f..1d373e8f4 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -104,7 +104,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
This value used to be fairly big (100K), but we must take into account that
if the server rejects the POST due for authentication reasons, this data
- will always be uncondtionally sent and thus it may not be larger than can
+ will always be unconditionally sent and thus it may not be larger than can
always be afforded to send twice.
It must not be greater than 64K to work on VMS.
@@ -172,8 +172,6 @@ struct HTTP {
size_t pauselen; /* the number of bytes left in data */
bool closed; /* TRUE on HTTP2 stream close */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
- uint32_t error_code; /* HTTP/2 error code */
-
char *mem; /* points to a buffer in memory to store received data */
size_t len; /* size of the buffer 'mem' points to */
size_t memlen; /* size of data copied to mem */
@@ -188,9 +186,6 @@ struct HTTP {
#endif
};
-typedef int (*sending)(void); /* Curl_send */
-typedef int (*recving)(void); /* Curl_recv */
-
#ifdef USE_NGHTTP2
/* h2 settings for this connection */
struct h2settings {
@@ -199,15 +194,14 @@ struct h2settings {
};
#endif
-
struct http_conn {
#ifdef USE_NGHTTP2
#define H2_BINSETTINGS_LEN 80
nghttp2_session *h2;
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
- sending send_underlying; /* underlying send Curl_send callback */
- recving recv_underlying; /* underlying recv Curl_recv callback */
+ Curl_send *send_underlying; /* underlying send Curl_send callback */
+ Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
char *inbuf; /* buffer to receive data from underlying socket */
size_t inbuflen; /* number of bytes filled in inbuf */
size_t nread_inbuf; /* number of bytes read from in inbuf */
@@ -226,6 +220,7 @@ struct http_conn {
/* list of settings that will be sent */
nghttp2_settings_entry local_settings[3];
size_t local_settings_num;
+ uint32_t error_code; /* HTTP/2 error code */
#else
int unused; /* prevent a compiler warning */
#endif
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index 699287940..da001dfd0 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,6 +41,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+#define H2_BUFSIZE 32768
#define MIN(x,y) ((x)<(y)?(x):(y))
#if (NGHTTP2_VERSION_NUM < 0x010000)
@@ -65,6 +66,22 @@
#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+#ifdef DEBUG_HTTP2
+#define H2BUGF(x) x
+#else
+#define H2BUGF(x) do { } WHILE_FALSE
+#endif
+
+
+static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err);
+static bool http2_connisdead(struct connectdata *conn);
+static int h2_session_send(struct Curl_easy *data,
+ nghttp2_session *h2);
+static int h2_process_pending_input(struct connectdata *conn,
+ struct http_conn *httpc,
+ CURLcode *err);
+
/*
* Curl_http2_init_state() is called when the easy handle is created and
* allows for HTTP/2 specific init of state.
@@ -91,6 +108,7 @@ static int http2_perform_getsock(const struct connectdata *conn,
int numsocks)
{
const struct http_conn *c = &conn->proto.httpc;
+ struct SingleRequest *k = &conn->data->req;
int bitmap = GETSOCK_BLANK;
(void)numsocks;
@@ -102,7 +120,9 @@ static int http2_perform_getsock(const struct connectdata *conn,
always be ready for one */
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
- if(nghttp2_session_want_write(c->h2))
+ /* we're still uploading or the HTTP/2 layer wants to send data */
+ if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
+ nghttp2_session_want_write(c->h2))
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
return bitmap;
@@ -140,13 +160,14 @@ static CURLcode http2_disconnect(struct connectdata *conn,
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
- DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+ H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
http2_stream_free(conn->data->req.protop);
+ conn->data->state.drain = 0;
- DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
+ H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
return CURLE_OK;
}
@@ -158,29 +179,54 @@ static CURLcode http2_disconnect(struct connectdata *conn,
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct connectdata *check)
+static bool http2_connisdead(struct connectdata *conn)
{
int sval;
- bool ret_val = TRUE;
+ bool dead = TRUE;
- sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
+ if(conn->bits.close)
+ return TRUE;
+
+ sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0);
if(sval == 0) {
/* timeout */
- ret_val = FALSE;
+ dead = FALSE;
}
else if(sval & CURL_CSELECT_ERR) {
/* socket is in an error state */
- ret_val = TRUE;
+ dead = TRUE;
}
else if(sval & CURL_CSELECT_IN) {
/* readable with no error. could still be closed */
- ret_val = !Curl_connalive(check);
+ dead = !Curl_connalive(conn);
+ if(!dead) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other thransfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t nread = -1;
+ if(httpc->recv_underlying)
+ /* if called "too early", this pointer isn't setup yet! */
+ nread = ((Curl_recv *)httpc->recv_underlying)(
+ conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ if(nread != -1) {
+ infof(conn->data,
+ "%d bytes stray data read before trying h2 connection\n",
+ (int)nread);
+ httpc->nread_inbuf = 0;
+ httpc->inbuflen = nread;
+ (void)h2_process_pending_input(conn, httpc, &result);
+ }
+ else
+ /* the read failed so let's say this is dead anyway */
+ dead = TRUE;
+ }
}
- return ret_val;
+ return dead;
}
-
static unsigned int http2_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
@@ -204,7 +250,6 @@ void Curl_http2_setup_req(struct Curl_easy *data)
http->status_code = -1;
http->pausedata = NULL;
http->pauselen = 0;
- http->error_code = NGHTTP2_NO_ERROR;
http->closed = FALSE;
http->close_handled = FALSE;
http->mem = data->state.buffer;
@@ -217,6 +262,7 @@ void Curl_http2_setup_conn(struct connectdata *conn)
{
conn->proto.httpc.settings.max_concurrent_streams =
DEFAULT_MAX_CONCURRENT_STREAMS;
+ conn->proto.httpc.error_code = NGHTTP2_NO_ERROR;
}
/*
@@ -428,7 +474,7 @@ static int push_promise(struct Curl_easy *data,
const nghttp2_push_promise *frame)
{
int rv;
- DEBUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
+ H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
frame->promised_stream_id));
if(data->multi->push_cb) {
struct HTTP *stream;
@@ -448,7 +494,7 @@ static int push_promise(struct Curl_easy *data,
heads.data = data;
heads.frame = frame;
/* ask the application */
- DEBUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
stream = data->req.protop;
if(!stream) {
@@ -458,9 +504,11 @@ static int push_promise(struct Curl_easy *data,
goto fail;
}
+ Curl_set_in_callback(data, true);
rv = data->multi->push_cb(data, newhandle,
stream->push_headers_used, &heads,
data->multi->push_userp);
+ Curl_set_in_callback(data, false);
/* free the headers again */
for(i = 0; i<stream->push_headers_used; i++)
@@ -497,7 +545,7 @@ static int push_promise(struct Curl_easy *data,
frame->promised_stream_id, newhandle);
}
else {
- DEBUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
rv = 1;
}
fail:
@@ -511,7 +559,6 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data_s = NULL;
struct HTTP *stream = NULL;
- static int lastStream = -1;
int rv;
size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id;
@@ -520,32 +567,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* stream ID zero is for connection-oriented stuff */
if(frame->hd.type == NGHTTP2_SETTINGS) {
uint32_t max_conn = httpc->settings.max_concurrent_streams;
- DEBUGF(infof(conn->data, "Got SETTINGS\n"));
+ H2BUGF(infof(conn->data, "Got SETTINGS\n"));
httpc->settings.max_concurrent_streams =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
httpc->settings.enable_push =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
- DEBUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
+ H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
httpc->settings.max_concurrent_streams));
- DEBUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
+ H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
httpc->settings.enable_push?"TRUE":"false"));
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
infof(conn->data,
- "Connection state changed (MAX_CONCURRENT_STREAMS updated)!\n");
+ "Connection state changed (MAX_CONCURRENT_STREAMS == %d)!\n",
+ httpc->settings.max_concurrent_streams);
Curl_multi_connchanged(conn->data->multi);
}
}
return 0;
}
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
- if(lastStream != stream_id) {
- lastStream = stream_id;
- }
if(!data_s) {
- DEBUGF(infof(conn->data,
+ H2BUGF(infof(conn->data,
"No Curl_easy associated with stream: %x\n",
stream_id));
return 0;
@@ -553,12 +598,12 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream = data_s->req.protop;
if(!stream) {
- DEBUGF(infof(conn->data, "No proto pointer for stream: %x\n",
+ H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
+ H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
frame->hd.type, stream_id));
switch(frame->hd.type) {
@@ -581,8 +626,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
/* nghttp2 guarantees that :status is received, and we store it to
- stream->status_code */
- DEBUGASSERT(stream->status_code != -1);
+ stream->status_code. Fuzzing has proven this can still be reached
+ without status code having been set. */
+ if(stream->status_code == -1)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* Only final status code signals the end of header */
if(stream->status_code / 100 != 1) {
@@ -600,7 +647,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
ncopy);
stream->nread_header_recvbuf += ncopy;
- DEBUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
+ H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
ncopy, stream_id, stream->mem));
stream->len -= ncopy;
@@ -629,7 +676,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
break;
default:
- DEBUGF(infof(conn->data, "Got frame type %x for stream %u!\n",
+ H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n",
frame->hd.type, stream_id));
break;
}
@@ -642,13 +689,13 @@ static int on_invalid_frame_recv(nghttp2_session *session,
{
struct Curl_easy *data_s = NULL;
(void)userp;
-#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)lib_error_code;
#endif
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s,
+ H2BUGF(infof(data_s,
"on_invalid_frame_recv() was called, error=%d:%s\n",
lib_error_code, nghttp2_strerror(lib_error_code)));
}
@@ -693,7 +740,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "%zu data received for stream %u "
+ H2BUGF(infof(data_s, "%zu data received for stream %u "
"(%zu left in buffer %p, total %zu)\n",
nread, stream_id,
stream->len, stream->mem,
@@ -702,7 +749,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
if(nread < len) {
stream->pausedata = data + nread;
stream->pauselen = len - nread;
- DEBUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
+ H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
", stream %u\n",
len - nread, stream_id));
data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
@@ -730,7 +777,7 @@ static int before_frame_send(nghttp2_session *session,
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s, "before_frame_send() was called\n"));
+ H2BUGF(infof(data_s, "before_frame_send() was called\n"));
}
return 0;
@@ -744,7 +791,7 @@ static int on_frame_send(nghttp2_session *session,
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
+ H2BUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
frame->hd.length));
}
return 0;
@@ -755,13 +802,13 @@ static int on_frame_not_send(nghttp2_session *session,
{
struct Curl_easy *data_s;
(void)userp;
-#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)lib_error_code;
#endif
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s,
+ H2BUGF(infof(data_s,
"on_frame_not_send() was called, lib_error_code = %d\n",
lib_error_code));
}
@@ -777,6 +824,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
(void)stream_id;
if(stream_id) {
+ struct http_conn *httpc;
/* get the stream from the hash based on Stream ID, stream ID zero is for
connection-oriented stuff */
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
@@ -785,20 +833,21 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
decided to reject stream (e.g., PUSH_PROMISE). */
return 0;
}
- DEBUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
+ H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
Curl_http2_strerror(error_code), error_code, stream_id));
stream = data_s->req.protop;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream->error_code = error_code;
stream->closed = TRUE;
data_s->state.drain++;
- conn->proto.httpc.drain_total++;
+ httpc = &conn->proto.httpc;
+ httpc->drain_total++;
+ httpc->error_code = error_code;
/* remove the entry from the hash as the stream is now gone */
nghttp2_session_set_stream_user_data(session, stream_id, 0);
- DEBUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+ H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
}
return 0;
}
@@ -815,7 +864,7 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- DEBUGF(infof(data_s, "on_begin_headers() was called\n"));
+ H2BUGF(infof(data_s, "on_begin_headers() was called\n"));
if(frame->hd.type != NGHTTP2_HEADERS) {
return 0;
@@ -826,16 +875,12 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- /* This is trailer HEADERS started. Allocate buffer for them. */
- DEBUGF(infof(data_s, "trailer field started\n"));
-
- DEBUGASSERT(stream->trailer_recvbuf == NULL);
-
- stream->trailer_recvbuf = Curl_add_buffer_init();
if(!stream->trailer_recvbuf) {
- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ stream->trailer_recvbuf = Curl_add_buffer_init();
+ if(!stream->trailer_recvbuf) {
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
}
-
return 0;
}
@@ -928,7 +973,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* 4 is for ": " and "\r\n". */
uint32_t n = (uint32_t)(namelen + valuelen + 4);
- DEBUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n));
@@ -956,7 +1001,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
+ H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
stream->status_code, data_s));
return 0;
}
@@ -972,7 +1017,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
value));
return 0; /* 0 is successful */
@@ -1021,15 +1066,13 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
else if(nread == 0)
return NGHTTP2_ERR_DEFERRED;
- DEBUGF(infof(data_s, "data_source_read_callback: "
+ H2BUGF(infof(data_s, "data_source_read_callback: "
"returns %zu bytes stream %u\n",
nread, stream_id));
return nread;
}
-#define H2_BUFSIZE 32768
-
#ifdef NGHTTP2_HAS_ERROR_CALLBACK
static int error_callback(nghttp2_session *session,
const char *msg,
@@ -1067,7 +1110,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
struct http_conn *httpc = &conn->proto.httpc;
if(http->header_recvbuf) {
- DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
@@ -1216,22 +1258,20 @@ static int should_close_session(struct http_conn *httpc)
!nghttp2_session_want_write(httpc->h2);
}
-static int h2_session_send(struct Curl_easy *data,
- nghttp2_session *h2);
-
/*
* h2_process_pending_input() processes pending input left in
* httpc->inbuf. Then, call h2_session_send() to send pending data.
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
-static int h2_process_pending_input(struct Curl_easy *data,
+static int h2_process_pending_input(struct connectdata *conn,
struct http_conn *httpc,
CURLcode *err)
{
ssize_t nread;
char *inbuf;
ssize_t rv;
+ struct Curl_easy *data = conn->data;
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
@@ -1246,7 +1286,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
if(nread == rv) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: All data in connection buffer "
"processed\n"));
httpc->inbuflen = 0;
@@ -1254,7 +1294,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
else {
httpc->nread_inbuf += rv;
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: %zu bytes left in connection "
"buffer\n",
httpc->inbuflen - httpc->nread_inbuf));
@@ -1267,9 +1307,15 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
- *err = CURLE_HTTP2;
+ if(httpc->error_code)
+ *err = CURLE_HTTP2;
+ else {
+ /* not an error per se, but should still close the connection */
+ connclose(conn, "GOAWAY received");
+ *err = CURLE_OK;
+ }
return -1;
}
@@ -1300,7 +1346,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id);
- (void)h2_process_pending_input(conn->data, httpc, &result);
+ (void)h2_process_pending_input(conn, httpc, &result);
}
}
return result;
@@ -1324,7 +1370,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
data->state.drain = 0;
if(httpc->pause_stream_id == 0) {
- if(h2_process_pending_input(data, httpc, err) != 0) {
+ if(h2_process_pending_input(conn, httpc, err) != 0) {
return -1;
}
}
@@ -1333,17 +1379,25 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
- if(stream->error_code != NGHTTP2_NO_ERROR) {
+ if(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
+ H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
+ stream->stream_id));
+ connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
+ data->state.refused_stream = TRUE;
+ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
+ return -1;
+ }
+ else if(httpc->error_code != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
- stream->stream_id, Curl_http2_strerror(stream->error_code),
- stream->error_code);
+ stream->stream_id, Curl_http2_strerror(httpc->error_code),
+ httpc->error_code);
*err = CURLE_HTTP2_STREAM;
return -1;
}
if(!stream->bodystarted) {
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
- " all response header fields, teated as error",
+ " all response header fields, treated as error",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
@@ -1370,7 +1424,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
stream->close_handled = TRUE;
- DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
+ H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
return 0;
}
@@ -1411,7 +1465,7 @@ static int h2_session_send(struct Curl_easy *data,
h2_pri_spec(data, &pri_spec);
- DEBUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
+ H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
stream->stream_id, data));
rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
&pri_spec);
@@ -1435,7 +1489,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"http2_recv: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
@@ -1461,16 +1515,16 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
ncopy);
stream->nread_header_recvbuf += ncopy;
- DEBUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
+ H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
(int)ncopy));
return ncopy;
}
- DEBUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
+ H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
data, stream->stream_id));
if((data->state.drain) && stream->memlen) {
- DEBUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
+ H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
stream->memlen, stream->stream_id,
stream->mem, mem));
if(mem != stream->mem) {
@@ -1484,7 +1538,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */
httpc->pause_stream_id = 0;
- if(h2_process_pending_input(data, httpc, &result) != 0) {
+ if(h2_process_pending_input(conn, httpc, &result) != 0) {
*err = result;
return -1;
}
@@ -1500,7 +1554,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
infof(data, "%zu data bytes written\n", nread);
if(stream->pauselen == 0) {
- DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
+ H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
httpc->pause_stream_id = 0;
@@ -1514,12 +1568,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called,
and stream could be hanged. */
- if(h2_process_pending_input(data, httpc, &result) != 0) {
+ if(h2_process_pending_input(conn, httpc, &result) != 0) {
*err = result;
return -1;
}
}
- DEBUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
nread, stream->stream_id));
return nread;
}
@@ -1532,7 +1586,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
socket is not read. But it seems that usually streams are
notified with its drain property, and socket is read again
quickly. */
- DEBUGF(infof(data, "stream %x is paused, pause id: %x\n",
+ H2BUGF(infof(data, "stream %x is paused, pause id: %x\n",
stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
@@ -1561,12 +1615,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
}
if(nread == 0) {
- failf(data, "Unexpected EOF");
- *err = CURLE_RECV_ERROR;
- return -1;
+ H2BUGF(infof(data, "end of stream\n"));
+ *err = CURLE_OK;
+ return 0;
}
- DEBUGF(infof(data, "nread=%zd\n", nread));
+ H2BUGF(infof(data, "nread=%zd\n", nread));
httpc->inbuflen = nread;
inbuf = httpc->inbuf;
@@ -1575,7 +1629,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
- DEBUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
+ H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
nread));
}
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
@@ -1586,15 +1640,15 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
*err = CURLE_RECV_ERROR;
return -1;
}
- DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
+ H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
if(nread == rv) {
- DEBUGF(infof(data, "All data in connection buffer processed\n"));
+ H2BUGF(infof(data, "All data in connection buffer processed\n"));
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
}
else {
httpc->nread_inbuf += rv;
- DEBUGF(infof(data, "%zu bytes left in connection buffer\n",
+ H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
httpc->inbuflen - httpc->nread_inbuf));
}
/* Always send pending frames in nghttp2 session, because
@@ -1606,21 +1660,21 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data, "http2_recv: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
- DEBUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
retlen, stream->stream_id));
stream->memlen = 0;
if(httpc->pause_stream_id == stream->stream_id) {
/* data for this stream is returned now, but this stream caused a pause
already so we need it called again asap */
- DEBUGF(infof(data, "Data returned for PAUSED stream %u\n",
+ H2BUGF(infof(data, "Data returned for PAUSED stream %u\n",
stream->stream_id));
}
else if(!stream->closed) {
@@ -1637,7 +1691,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
return http2_handle_stream_close(conn, data, stream, err);
}
*err = CURLE_AGAIN;
- DEBUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
+ H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
stream->stream_id));
return -1;
}
@@ -1739,7 +1793,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
(void)sockindex;
- DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
+ H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
@@ -1768,7 +1822,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
stream->upload_len = 0;
if(should_close_session(httpc)) {
- DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -1781,7 +1835,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nghttp2_session_resume_data(h2, stream->stream_id);
}
- DEBUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
+ H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
stream->stream_id));
return len;
}
@@ -1809,8 +1863,11 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
return -1;
}
- /* Extract :method, :path from request line */
- line_end = strstr(hdbuf, "\r\n");
+ /* Extract :method, :path from request line
+ We do line endings with CRLF so checking for CR is enough */
+ line_end = memchr(hdbuf, '\r', len);
+ if(!line_end)
+ goto fail;
/* Method does not contain spaces */
end = memchr(hdbuf, ' ', line_end - hdbuf);
@@ -1868,8 +1925,10 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
hdbuf = line_end + 2;
- line_end = strstr(hdbuf, "\r\n");
- if(line_end == hdbuf)
+ /* check for next CR, but only within the piece of data left in the given
+ buffer */
+ line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem));
+ if(!line_end || (line_end == hdbuf))
goto fail;
/* header continuation lines are not supported */
@@ -1937,7 +1996,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen;
- DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
+ H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
@@ -1975,7 +2034,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
Curl_safefree(nva);
if(stream_id < 0) {
- DEBUGF(infof(conn->data, "http2_send() send error\n"));
+ H2BUGF(infof(conn->data, "http2_send() send error\n"));
*err = CURLE_SEND_ERROR;
return -1;
}
@@ -1994,7 +2053,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -2078,8 +2137,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
if(result)
return result;
- httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
- httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
+ httpc->recv_underlying = conn->recv[FIRSTSOCKET];
+ httpc->send_underlying = conn->send[FIRSTSOCKET];
conn->recv[FIRSTSOCKET] = http2_recv;
conn->send[FIRSTSOCKET] = http2_send;
@@ -2152,7 +2211,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
return CURLE_HTTP2;
}
- DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
+ H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
if((ssize_t)nread == nproc) {
httpc->inbuflen = 0;
@@ -2172,7 +2231,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"nghttp2_session_send(): nothing to do in this session\n"));
return CURLE_HTTP2;
}
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index 161642969..18dfcb282 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -74,14 +74,18 @@
*/
+#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
- We avoid the use of isxdigit to accommodate non-ASCII hosts. */
-static bool Curl_isxdigit(char digit)
+ We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
+static bool Curl_isxdigit_ascii(char digit)
{
- return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
+ return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
|| (digit >= 0x41 && digit <= 0x46) /* A-F */
- || (digit >= 0x61 && digit <= 0x66) /* a-f */) ? TRUE : FALSE;
+ || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
+#else
+#define Curl_isxdigit_ascii(x) Curl_isxdigit(x)
+#endif
void Curl_httpchunk_init(struct connectdata *conn)
{
@@ -128,7 +132,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(Curl_isxdigit(*datap)) {
+ if(Curl_isxdigit_ascii(*datap)) {
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
@@ -187,15 +191,15 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
/* Write the data portion available */
- if(conn->data->set.http_ce_skip || !k->writer_stack) {
- if(!k->ignorebody)
+ if(!conn->data->set.http_te_skip && !k->ignorebody) {
+ if(!conn->data->set.http_ce_skip && k->writer_stack)
+ result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
+ else
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
- }
- else
- result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
- if(result)
- return CHUNKE_WRITE_ERROR;
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
*wrote += piece;
ch->datasize -= piece; /* decrease amount left to expect */
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index 51375e81d..ddcd65b3b 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -89,7 +89,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
}
}
- /* Initilise the security context and decode our challenge */
+ /* Initialize the security context and decode our challenge */
result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
host, header, neg_ctx);
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index 0f1edcf65..fd5540b5d 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -121,9 +121,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
server, which is for a plain host or for a HTTP proxy */
char **allocuserpwd;
- /* point to the name and password for this */
+ /* point to the username, password, service and host */
const char *userp;
const char *passwdp;
+ const char *service = NULL;
+ const char *hostname = NULL;
/* point to the correct struct with this */
struct ntlmdata *ntlm;
@@ -141,6 +143,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
+ service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
+ conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+ hostname = conn->http_proxy.host.name;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}
@@ -148,6 +153,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &conn->allocptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
+ service = conn->data->set.str[STRING_SERVICE_NAME] ?
+ conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
+ hostname = conn->host.name;
ntlm = &conn->ntlm;
authp = &conn->data->state.authhost;
}
@@ -174,7 +182,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
- ntlm, &base64, &len);
+ service, hostname,
+ ntlm, &base64,
+ &len);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index 7f5040543..e10a48829 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -221,7 +221,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!req_buffer)
return CURLE_OUT_OF_MEMORY;
- host_port = aprintf("%s:%hu", hostname, remote_port);
+ host_port = aprintf("%s:%d", hostname, remote_port);
if(!host_port) {
Curl_add_buffer_free(req_buffer);
return CURLE_OUT_OF_MEMORY;
@@ -245,14 +245,14 @@ static CURLcode CONNECT(struct connectdata *conn,
if(hostname != conn->host.name)
ipv6_ip = (strchr(hostname, ':') != NULL);
hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%hu", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
Curl_add_buffer_free(req_buffer);
return CURLE_OUT_OF_MEMORY;
}
- if(!Curl_checkProxyheaders(conn, "Host:")) {
+ if(!Curl_checkProxyheaders(conn, "Host")) {
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
@@ -260,10 +260,10 @@ static CURLcode CONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
}
- if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
+ if(!Curl_checkProxyheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 70507df2d..59c0d71a8 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -85,7 +85,7 @@ krb5_decode(void *app_data, void *buf, int len,
enc.value = buf;
enc.length = len;
- maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL);
+ maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL);
if(maj != GSS_S_COMPLETE) {
if(len >= 4)
strcpy(buf, "599 ");
@@ -119,11 +119,11 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
int len;
/* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
- * libraries modify the input buffer in gss_seal()
+ * libraries modify the input buffer in gss_wrap()
*/
dec.value = (void *)from;
dec.length = length;
- maj = gss_seal(&min, *context,
+ maj = gss_wrap(&min, *context,
level == PROT_PRIVATE,
GSS_C_QOP_DEFAULT,
&dec, &state, &enc);
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index 80301a141..3096602b7 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -484,6 +484,11 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx)
#endif /* CRYPTO LIBS */
+/* Disable this picky gcc-8 compiler warning */
+#if defined(__GNUC__) && (__GNUC__ >= 8)
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
const HMAC_params Curl_HMAC_MD5[] = {
{
(HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index e0853a9ed..4c0d2eeba 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -51,10 +51,6 @@
#endif
-#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
-#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
-#define DISPOSITION_DEFAULT "attachment"
-
#define READ_ERROR ((size_t) -1)
/* Encoders. */
@@ -245,7 +241,7 @@ static FILE * vmsfopenread(const char *file, const char *mode)
static char *Curl_basename(char *path)
{
/* Ignore all the details above for now and make a quick and simple
- implementaion here */
+ implementation here */
char *s1;
char *s2;
@@ -1197,7 +1193,10 @@ CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
}
/* Duplicate other fields. */
- dst->encoder = src->encoder;
+ if(dst != NULL)
+ dst->encoder = src->encoder;
+ else
+ res = CURLE_WRITE_ERROR;
if(!res)
res = curl_mime_type(dst, src->mimetype);
if(!res)
@@ -1206,7 +1205,7 @@ CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
res = curl_mime_filename(dst, src->filename);
/* If an error occurred, rollback. */
- if(res)
+ if(res && dst)
Curl_mime_cleanpart(dst);
return res;
@@ -1642,8 +1641,7 @@ static CURLcode add_content_type(struct curl_slist **slp,
boundary? boundary: "");
}
-
-static const char *ContentTypeForFilename(const char *filename)
+const char *Curl_mime_contenttype(const char *filename)
{
unsigned int i;
@@ -1715,14 +1713,14 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
break;
case MIMEKIND_FILE:
- contenttype = ContentTypeForFilename(part->filename);
+ contenttype = Curl_mime_contenttype(part->filename);
if(!contenttype)
- contenttype = ContentTypeForFilename(part->data);
+ contenttype = Curl_mime_contenttype(part->data);
if(!contenttype && part->filename)
contenttype = FILE_CONTENTTYPE_DEFAULT;
break;
default:
- contenttype = ContentTypeForFilename(part->filename);
+ contenttype = Curl_mime_contenttype(part->filename);
break;
}
}
diff --git a/Utilities/cmcurl/lib/mime.h b/Utilities/cmcurl/lib/mime.h
index 920a8a77a..4d5c70404 100644
--- a/Utilities/cmcurl/lib/mime.h
+++ b/Utilities/cmcurl/lib/mime.h
@@ -30,6 +30,10 @@
#define MIME_USERHEADERS_OWNER (1 << 0)
#define MIME_BODY_ONLY (1 << 1)
+#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
+#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
+#define DISPOSITION_DEFAULT "attachment"
+
/* Part source kinds. */
enum mimekind {
MIMEKIND_NONE = 0, /* Part not set. */
@@ -134,5 +138,6 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
void *instream);
CURLcode Curl_mime_rewind(curl_mimepart *part);
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+const char *Curl_mime_contenttype(const char *filename);
#endif /* HEADER_CURL_MIME_H */
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 43823cc93..f85284695 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,6 +77,7 @@ static CURLMcode add_next_timeout(struct curltime now,
struct Curl_easy *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
+static void process_pending_handles(struct Curl_multi *multi);
#ifdef DEBUGBUILD
static const char * const statename[]={
@@ -366,6 +367,9 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
if(data->multi)
return CURLM_ADDED_ALREADY;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
/* Initialize timeout list for this handle */
Curl_llist_init(&data->state.timeoutlist, NULL);
@@ -375,6 +379,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
* potential multi's connection cache growing which won't be undone in this
* function no matter what.
*/
+ if(data->set.errorbuffer)
+ data->set.errorbuffer[0] = 0;
/* set the easy handle */
multistate(data, CURLM_STATE_INIT);
@@ -535,13 +541,14 @@ static CURLcode multi_done(struct connectdata **connp,
result = CURLE_ABORTED_BY_CALLBACK;
}
- if(conn->send_pipe.size + conn->recv_pipe.size != 0 &&
- !data->set.reuse_forbid &&
- !conn->bits.close) {
- /* Stop if pipeline is not empty and we do not have to close
- connection. */
+ process_pending_handles(data->multi); /* connection / multiplex */
+
+ if(conn->send_pipe.size || conn->recv_pipe.size) {
+ /* Stop if pipeline is not empty . */
data->easy_conn = NULL;
- DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
+ DEBUGF(infof(data, "Connection still in use %d/%d, "
+ "no more multi_done now!\n",
+ conn->send_pipe.size, conn->recv_pipe.size));
return CURLE_OK;
}
@@ -640,6 +647,9 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
if(!data->multi)
return CURLM_OK; /* it is already removed so let's say it is fine! */
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
TRUE : FALSE;
@@ -650,10 +660,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* this handle is "alive" so we need to count down the total number of
alive connections when this is removed */
multi->num_alive--;
-
- /* When this handle gets removed, other handles may be able to get the
- connection */
- Curl_multi_process_pending_handles(multi);
}
if(data->easy_conn &&
@@ -903,6 +909,9 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
data = multi->easyp;
while(data) {
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
@@ -956,6 +965,9 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
/* If the internally desired timeout is actually shorter than requested from
the outside, then use the shorter time! But only if the internal timer
is actually larger than -1! */
@@ -1121,6 +1133,9 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
{
CURLMcode rc;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
rc = curl_multi_add_handle(multi, data);
if(!rc) {
struct SingleRequest *k = &data->req;
@@ -1327,7 +1342,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(multi_ischanged(multi, TRUE)) {
DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
- Curl_multi_process_pending_handles(multi);
+ process_pending_handles(multi); /* pipelined/multiplexed */
}
if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
@@ -1773,16 +1788,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_DO_DONE:
/* Move ourselves from the send to recv pipeline */
Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+ /* Check if we can move pending requests to send pipe */
+ process_pending_handles(multi); /* pipelined/multiplexed */
/* Only perform the transfer if there's a good socket to work with.
Having both BAD is a signal to skip immediately to DONE */
if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
(data->easy_conn->writesockfd != CURL_SOCKET_BAD))
multistate(data, CURLM_STATE_WAITPERFORM);
- else
- {
+ else {
if(data->state.wildcardmatch &&
((data->easy_conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
data->wildcard.state = CURLWC_DONE;
@@ -1811,22 +1827,26 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
- send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now);
+ send_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
- recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now);
-
- if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
+ recv_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now);
+
+ if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
+ Curl_ratelimit(data, now);
+ }
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
@@ -1858,7 +1878,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_start,
now);
- if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
+ if(send_timeout_ms || recv_timeout_ms) {
+ Curl_ratelimit(data, now);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
@@ -1926,9 +1947,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->easy_conn->recv_pipe.head)
Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
-
/* When we follow redirects or is set to retry the connection, we must
to go back to the CONNECT state */
if(data->req.newurl || retry) {
@@ -1985,8 +2003,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Remove ourselves from the receive pipeline, if we are there. */
Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+ /* Check if we can move pending requests to connection */
+ process_pending_handles(multi); /* pipelined/multiplexing */
/* post-transfer command */
res = multi_done(&data->easy_conn, result, FALSE);
@@ -2054,7 +2074,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->state.pipe_broke = FALSE;
/* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+ process_pending_handles(multi); /* connection */
if(data->easy_conn) {
/* if this has a connection, unsubscribe from the pipelines */
@@ -2127,6 +2147,9 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
data = multi->easyp;
while(data) {
CURLMcode result;
@@ -2174,6 +2197,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
struct Curl_easy *nextdata;
if(GOOD_MULTI_HANDLE(multi)) {
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
multi->type = 0; /* not good anymore */
/* Firsrt remove all remaining easy handles */
@@ -2234,7 +2260,9 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
*msgs_in_queue = 0; /* default to none */
- if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(&multi->msglist)) {
+ if(GOOD_MULTI_HANDLE(multi) &&
+ !multi->in_callback &&
+ Curl_llist_count(&multi->msglist)) {
/* there is one or more messages in the list */
struct curl_llist_element *e;
@@ -2396,6 +2424,12 @@ static void singlesocket(struct Curl_multi *multi,
data->numsocks = num;
}
+void Curl_updatesocket(struct Curl_easy *data)
+{
+ singlesocket(data->multi, data);
+}
+
+
/*
* Curl_multi_closed()
*
@@ -2624,6 +2658,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
va_start(param, option);
switch(option) {
@@ -2688,7 +2725,10 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
int *running_handles)
{
- CURLMcode result = multi_socket(multi, FALSE, s, 0, running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, FALSE, s, 0, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
@@ -2697,8 +2737,10 @@ CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
int ev_bitmask, int *running_handles)
{
- CURLMcode result = multi_socket(multi, FALSE, s,
- ev_bitmask, running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
@@ -2707,8 +2749,10 @@ CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
{
- CURLMcode result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0,
- running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
@@ -2760,6 +2804,9 @@ CURLMcode curl_multi_timeout(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
return multi_timeout(multi, timeout_ms);
}
@@ -2992,6 +3039,9 @@ CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
{
struct Curl_sh_entry *there = NULL;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
there = sh_getentry(&multi->sockhash, s);
if(!there)
@@ -3032,28 +3082,38 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
return &multi->pipelining_server_bl;
}
-void Curl_multi_process_pending_handles(struct Curl_multi *multi)
+static void process_pending_handles(struct Curl_multi *multi)
{
struct curl_llist_element *e = multi->pending.head;
-
- while(e) {
+ if(e) {
struct Curl_easy *data = e->ptr;
- struct curl_llist_element *next = e->next;
- if(data->mstate == CURLM_STATE_CONNECT_PEND) {
- multistate(data, CURLM_STATE_CONNECT);
+ DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND);
- /* Remove this node from the list */
- Curl_llist_remove(&multi->pending, e, NULL);
+ multistate(data, CURLM_STATE_CONNECT);
- /* Make sure that the handle will be processed soonish. */
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- }
+ /* Remove this node from the list */
+ Curl_llist_remove(&multi->pending, e, NULL);
- e = next; /* operate on next handle */
+ /* Make sure that the handle will be processed soonish. */
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
+void Curl_set_in_callback(struct Curl_easy *easy, bool value)
+{
+ if(easy->multi_easy)
+ easy->multi_easy->in_callback = value;
+ else if(easy->multi)
+ easy->multi->in_callback = value;
+}
+
+bool Curl_is_in_callback(struct Curl_easy *easy)
+{
+ return ((easy->multi && easy->multi->in_callback) ||
+ (easy->multi_easy && easy->multi_easy->in_callback));
+}
+
#ifdef DEBUGBUILD
void Curl_multi_dump(struct Curl_multi *multi)
{
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index de9a7cf59..1a5017f4a 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -146,6 +146,7 @@ struct Curl_multi {
void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */
+ bool in_callback; /* true while executing a callback */
};
#endif /* HEADER_CURL_MULTIHANDLE_H */
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index a877571a0..c8fb5ca0d 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,11 +26,14 @@
* Prototypes for library-wide functions provided by multi.c
*/
+void Curl_updatesocket(struct Curl_easy *data);
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
void Curl_expire_clear(struct Curl_easy *data);
void Curl_expire_done(struct Curl_easy *data, expire_id id);
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+void Curl_set_in_callback(struct Curl_easy *data, bool value);
+bool Curl_is_in_callback(struct Curl_easy *easy);
/* Internal version of curl_multi_init() accepts size parameters for the
socket and connection hashes */
@@ -56,8 +59,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
void Curl_multi_dump(struct Curl_multi *multi);
#endif
-void Curl_multi_process_pending_handles(struct Curl_multi *multi);
-
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index 92b2f8d73..14143248f 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -30,6 +30,7 @@
#include "formdata.h"
#include "sendf.h"
#include "urldata.h"
+#include "multiif.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -84,7 +85,10 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
{
if(data && data->set.convtonetwork) {
/* use translation callback */
- CURLcode result = data->set.convtonetwork(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convtonetwork(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
@@ -147,7 +151,10 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
{
if(data && data->set.convfromnetwork) {
/* use translation callback */
- CURLcode result = data->set.convfromnetwork(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convfromnetwork(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
@@ -210,7 +217,10 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
{
if(data && data->set.convfromutf8) {
/* use translation callback */
- CURLcode result = data->set.convfromutf8(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convfromutf8(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index 290cbe31f..215d933ac 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.c
@@ -186,11 +186,9 @@ int GetOrSetUpData(int id, libdata_t **appData,
app_data = (libdata_t *) get_app_data(id);
if(!app_data) {
- app_data = malloc(sizeof(libdata_t));
+ app_data = calloc(1, sizeof(libdata_t));
if(app_data) {
- memset(app_data, 0, sizeof(libdata_t));
-
app_data->tenbytes = malloc(10);
app_data->lock = NXMutexAlloc(0, 0, &liblock);
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index f2ffdfe67..c6cb79434 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, 2017, Howard Chu, <hyc@openldap.org>
- * Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -221,7 +221,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
if(conn->handler->flags & PROTOPT_SSL)
*ptr++ = 's';
snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
- conn->host.name, conn->remote_port);
+ conn->host.name, conn->remote_port);
#ifdef CURL_OPENLDAP_DEBUG
static int do_trace = 0;
@@ -286,7 +286,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
tvp = &tv;
-retry:
+ retry:
if(!li->didbind) {
char *binddn;
struct berval passwd;
@@ -472,8 +472,8 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
return ret;
for(ent = ldap_first_message(li->ld, msg); ent;
- ent = ldap_next_message(li->ld, ent)) {
- struct berval bv, *bvals, **bvp = &bvals;
+ ent = ldap_next_message(li->ld, ent)) {
+ struct berval bv, *bvals;
int binary = 0, msgtype;
CURLcode writeerr;
@@ -535,18 +535,40 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
}
data->req.bytecount += bv.bv_len + 5;
- for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
- rc == LDAP_SUCCESS;
- rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
+ for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
+ rc == LDAP_SUCCESS;
+ rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
int i;
- if(bv.bv_val == NULL) break;
+ if(bv.bv_val == NULL)
+ break;
if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
binary = 1;
else
binary = 0;
+ if(bvals == NULL) {
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ data->req.bytecount += bv.bv_len + 3;
+ continue;
+ }
+
for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
@@ -555,24 +577,24 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
- bv.bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
data->req.bytecount += bv.bv_len + 2;
if(!binary) {
/* check for leading or trailing whitespace */
if(ISSPACE(bvals[i].bv_val[0]) ||
- ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
+ ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
binval = 1;
else {
/* check for unprintable characters */
@@ -610,7 +632,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += 2;
if(val_b64_sz > 0) {
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
- val_b64_sz);
+ val_b64_sz);
if(writeerr) {
*err = writeerr;
return -1;
diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c
index 0fabbd269..3d3c00b4f 100644
--- a/Utilities/cmcurl/lib/parsedate.c
+++ b/Utilities/cmcurl/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -119,6 +119,7 @@ static int parsedate(const char *date, time_t *output);
#define tDAYZONE -60 /* offset for daylight savings time */
static const struct tzinfo tz[]= {
{"GMT", 0}, /* Greenwich Mean */
+ {"UT", 0}, /* Universal Time */
{"UTC", 0}, /* Universal (Coordinated) */
{"WET", 0}, /* Western European */
{"BST", 0 tDAYZONE}, /* British Summer */
@@ -276,26 +277,23 @@ struct my_tm {
int tm_hour;
int tm_mday;
int tm_mon;
- int tm_year;
+ int tm_year; /* full year */
};
/* struct tm to time since epoch in GMT time zone.
* This is similar to the standard mktime function but for GMT only, and
* doesn't suffer from the various bugs and portability problems that
* some systems' implementations have.
+ *
+ * Returns 0 on success, otherwise non-zero.
*/
-static time_t my_timegm(struct my_tm *tm)
+static void my_timegm(struct my_tm *tm, time_t *t)
{
static const int month_days_cumulative [12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int month, year, leap_days;
- if(tm->tm_year < 70)
- /* we don't support years before 1970 as they will cause this function
- to return a negative value */
- return -1;
-
- year = tm->tm_year + 1900;
+ year = tm->tm_year;
month = tm->tm_mon;
if(month < 0) {
year += (11 - month) / 12;
@@ -310,9 +308,9 @@ static time_t my_timegm(struct my_tm *tm)
leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
- (1969 / 4) + (1969 / 100) - (1969 / 400));
- return ((((time_t) (year - 1970) * 365
- + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
- + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+ *t = ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24
+ + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
}
/*
@@ -436,7 +434,7 @@ static int parsedate(const char *date, time_t *output)
tzoff = (val/100 * 60 + val%100)*60;
/* the + and - prefix indicates the local time compared to GMT,
- this we need ther reversed math to get what we want */
+ this we need their reversed math to get what we want */
tzoff = date[-1]=='+'?-tzoff:tzoff;
}
@@ -462,7 +460,7 @@ static int parsedate(const char *date, time_t *output)
if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
yearnum = val;
found = TRUE;
- if(yearnum < 1900) {
+ if(yearnum < 100) {
if(yearnum > 70)
yearnum += 1900;
else
@@ -491,18 +489,39 @@ static int parsedate(const char *date, time_t *output)
/* lacks vital info, fail */
return PARSEDATE_FAIL;
-#if SIZEOF_TIME_T < 5
- /* 32 bit time_t can only hold dates to the beginning of 2038 */
- if(yearnum > 2037) {
- *output = 0x7fffffff;
- return PARSEDATE_LATER;
+#ifdef HAVE_TIME_T_UNSIGNED
+ if(yearnum < 1970) {
+ /* only positive numbers cannot return earlier */
+ *output = TIME_T_MIN;
+ return PARSEDATE_SOONER;
}
#endif
- if(yearnum < 1970) {
- *output = 0;
+#if (SIZEOF_TIME_T < 5)
+
+#ifdef HAVE_TIME_T_UNSIGNED
+ /* an unsigned 32 bit time_t can only hold dates to 2106 */
+ if(yearnum > 2105) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER;
+ }
+#else
+ /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */
+ if(yearnum > 2037) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER;
+ }
+ if(yearnum < 1903) {
+ *output = TIME_T_MIN;
return PARSEDATE_SOONER;
}
+#endif
+
+#else
+ /* The Gregorian calendar was introduced 1582 */
+ if(yearnum < 1583)
+ return PARSEDATE_FAIL;
+#endif
if((mdaynum > 31) || (monnum > 11) ||
(hournum > 23) || (minnum > 59) || (secnum > 60))
@@ -513,31 +532,25 @@ static int parsedate(const char *date, time_t *output)
tm.tm_hour = hournum;
tm.tm_mday = mdaynum;
tm.tm_mon = monnum;
- tm.tm_year = yearnum - 1900;
-
- /* my_timegm() returns a time_t. time_t is often 32 bits, even on many
- architectures that feature 64 bit 'long'.
+ tm.tm_year = yearnum;
- Some systems have 64 bit time_t and deal with years beyond 2038. However,
- even on some of the systems with 64 bit time_t mktime() returns -1 for
- dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
+ /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on
+ architectures that feature 64 bit 'long' but ultimately time_t is the
+ correct data type to use.
*/
- t = my_timegm(&tm);
-
- /* time zone adjust (cast t to int to compare to negative one) */
- if(-1 != (int)t) {
+ my_timegm(&tm, &t);
- /* Add the time zone diff between local time zone and GMT. */
- long delta = (long)(tzoff!=-1?tzoff:0);
+ /* Add the time zone diff between local time zone and GMT. */
+ if(tzoff == -1)
+ tzoff = 0;
- if((delta>0) && (t > LONG_MAX - delta)) {
- *output = 0x7fffffff;
- return PARSEDATE_LATER; /* time_t overflow */
- }
-
- t += delta;
+ if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER; /* time_t overflow */
}
+ t += tzoff;
+
*output = t;
return PARSEDATE_OK;
@@ -549,10 +562,10 @@ time_t curl_getdate(const char *p, const time_t *now)
int rc = parsedate(p, &parsed);
(void)now; /* legacy argument from the past that we ignore */
- switch(rc) {
- case PARSEDATE_OK:
- case PARSEDATE_LATER:
- case PARSEDATE_SOONER:
+ if(rc == PARSEDATE_OK) {
+ if(parsed == -1)
+ /* avoid returning -1 for a working scenario */
+ parsed++;
return parsed;
}
/* everything else is fail */
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index 438856a99..ad370ee82 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -304,7 +304,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
* it would have been populated with something of size int to begin
* with, even though its datatype may be larger than an int.
*/
- DEBUGASSERT((ptr + pp->cache_size) <= (buf + data->set.buffer_size + 1));
+ if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) {
+ failf(data, "cached response data too big to handle");
+ return CURLE_RECV_ERROR;
+ }
memcpy(ptr, pp->cache, pp->cache_size);
gotbytes = (ssize_t)pp->cache_size;
free(pp->cache); /* free the cache */
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index cc5e8be79..f59faa3d3 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -24,9 +24,13 @@
#include "urldata.h"
#include "sendf.h"
+#include "multiif.h"
#include "progress.h"
#include "curl_printf.h"
+/* check rate limits within this many recent milliseconds, at minimum. */
+#define MIN_RATE_LIMIT_PERIOD 3000
+
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
byte) */
static void time2str(char *r, curl_off_t seconds)
@@ -234,11 +238,12 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
+ Curl_ratelimit(data, data->progress.start);
}
/*
- * This is used to handle speed limits, calculating how much milliseconds we
- * need to wait until we're back under the speed limit, if needed.
+ * This is used to handle speed limits, calculating how many milliseconds to
+ * wait until we're back under the speed limit, if needed.
*
* The way it works is by having a "starting point" (time & amount of data
* transferred by then) used in the speed computation, to be used instead of
@@ -250,73 +255,87 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
* the starting point, the limit (in bytes/s), the time of the starting point
* and the current time.
*
- * Returns -1 if no waiting is needed (not enough data transferred since
- * starting point yet), 0 when no waiting is needed but the starting point
- * should be reset (to current), or the number of milliseconds to wait to get
- * back under the speed limit.
+ * Returns 0 if no waiting is needed or when no waiting is needed but the
+ * starting point should be reset (to current); or the number of milliseconds
+ * to wait to get back under the speed limit.
*/
-long Curl_pgrsLimitWaitTime(curl_off_t cursize,
- curl_off_t startsize,
- curl_off_t limit,
- struct curltime start,
- struct curltime now)
+timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct curltime start,
+ struct curltime now)
{
curl_off_t size = cursize - startsize;
time_t minimum;
time_t actual;
- /* we don't have a starting point yet -- return 0 so it gets (re)set */
- if(start.tv_sec == 0 && start.tv_usec == 0)
+ if(!limit || !size)
return 0;
- /* not enough data yet */
- if(size < limit)
- return -1;
+ /*
+ * 'minimum' is the number of milliseconds 'size' should take to download to
+ * stay below 'limit'.
+ */
+ if(size < CURL_OFF_T_MAX/1000)
+ minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ else {
+ minimum = (time_t) (size / limit);
+ if(minimum < TIME_T_MAX/1000)
+ minimum *= 1000;
+ else
+ minimum = TIME_T_MAX;
+ }
- minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ /*
+ * 'actual' is the time in milliseconds it took to actually download the
+ * last 'size' bytes.
+ */
actual = Curl_timediff(now, start);
-
- if(actual < minimum)
- /* this is a conversion on some systems (64bit time_t => 32bit long) */
- return (long)(minimum - actual);
+ if(actual < minimum) {
+ /* if it downloaded the data faster than the limit, make it wait the
+ difference */
+ return (minimum - actual);
+ }
return 0;
}
+/*
+ * Set the number of downloaded bytes so far.
+ */
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.downloaded = size;
+}
- /* download speed limit */
- if((data->set.max_recv_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now) == 0)) {
- data->progress.dl_limit_start = now;
- data->progress.dl_limit_size = size;
+/*
+ * Update the timestamp and sizestamp to use for rate limit calculations.
+ */
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
+{
+ /* don't set a new stamp unless the time since last update is long enough */
+ if(data->set.max_recv_speed > 0) {
+ if(Curl_timediff(now, data->progress.dl_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.dl_limit_start = now;
+ data->progress.dl_limit_size = data->progress.downloaded;
+ }
+ }
+ if(data->set.max_send_speed > 0) {
+ if(Curl_timediff(now, data->progress.ul_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.ul_limit_start = now;
+ data->progress.ul_limit_size = data->progress.uploaded;
+ }
}
}
+/*
+ * Set the number of uploaded bytes so far.
+ */
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.uploaded = size;
-
- /* upload speed limit */
- if((data->set.max_send_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now) == 0)) {
- data->progress.ul_limit_start = now;
- data->progress.ul_limit_size = size;
- }
}
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
@@ -461,22 +480,26 @@ int Curl_pgrsUpdate(struct connectdata *conn)
if(data->set.fxferinfo) {
/* There's a callback set, call that */
+ Curl_set_in_callback(data, true);
result = data->set.fxferinfo(data->set.progress_client,
data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
+ Curl_set_in_callback(data, false);
if(result)
failf(data, "Callback aborted");
return result;
}
if(data->set.fprogress) {
/* The older deprecated callback is set, call that */
+ Curl_set_in_callback(data, true);
result = data->set.fprogress(data->set.progress_client,
(double)data->progress.size_dl,
(double)data->progress.downloaded,
(double)data->progress.size_ul,
(double)data->progress.uploaded);
+ Curl_set_in_callback(data, false);
if(result)
failf(data, "Callback aborted");
return result;
diff --git a/Utilities/cmcurl/lib/progress.h b/Utilities/cmcurl/lib/progress.h
index 9333ab25c..2baa925db 100644
--- a/Utilities/cmcurl/lib/progress.h
+++ b/Utilities/cmcurl/lib/progress.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,14 +46,15 @@ void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
-long Curl_pgrsLimitWaitTime(curl_off_t cursize,
- curl_off_t startsize,
- curl_off_t limit,
- struct curltime start,
- struct curltime now);
+timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct curltime start,
+ struct curltime now);
/* Don't show progress for sizes smaller than: */
#define LEAST_SIZE_PROGRESS BUFSIZE
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index 925da2c1a..41f300013 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@
* -incoming server requests
* -server CSeq counter
* -digest authentication
- * -connect thru proxy
+ * -connect through proxy
* -pipelining?
*/
@@ -357,7 +357,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport:");
+ p_transport = Curl_checkheaders(conn, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
@@ -381,11 +381,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept:")?
+ p_accept = Curl_checkheaders(conn, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
@@ -402,11 +402,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent;
}
@@ -421,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
conn->allocptr.ref = NULL;
@@ -438,7 +438,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
- if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
+ if(!Curl_checkheaders(conn, "Range") && data->state.range) {
Curl_safefree(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline;
@@ -448,11 +448,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq:")) {
+ if(Curl_checkheaders(conn, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session:")) {
+ if(Curl_checkheaders(conn, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -542,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
- if(!Curl_checkheaders(conn, "Content-Length:")) {
+ if(!Curl_checkheaders(conn, "Content-Length")) {
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
@@ -552,7 +552,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
@@ -561,7 +561,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
@@ -764,13 +764,14 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
writeit = data->set.fwrite_rtp;
user_ptr = data->set.rtp_out;
}
- else
- {
+ else {
writeit = data->set.fwrite_func;
user_ptr = data->set.out;
}
+ Curl_set_in_callback(data, true);
wrote = writeit(ptr, 1, len, user_ptr);
+ Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
failf(data, "Cannot pause RTP");
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 027f97c47..27c0ccc73 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,6 +37,7 @@
#include "connect.h"
#include "vtls/vtls.h"
#include "ssh.h"
+#include "easyif.h"
#include "multiif.h"
#include "non-ascii.h"
#include "strerror.h"
@@ -388,7 +389,7 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefor
+ due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
(EINPROGRESS == err)
@@ -455,7 +456,7 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefor
+ due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
@@ -540,18 +541,20 @@ static CURLcode pausewrite(struct Curl_easy *data,
}
-/* Curl_client_chop_write() writes chunks of data not larger than
- * CURL_MAX_WRITE_SIZE via client write callback(s) and
- * takes care of pause requests from the callbacks.
+/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via
+ * client write callback(s) and takes care of pause requests from the
+ * callbacks.
*/
-CURLcode Curl_client_chop_write(struct connectdata *conn,
- int type,
- char *ptr,
- size_t len)
+static CURLcode chop_write(struct connectdata *conn,
+ int type,
+ char *optr,
+ size_t olen)
{
struct Curl_easy *data = conn->data;
curl_write_callback writeheader = NULL;
curl_write_callback writebody = NULL;
+ char *ptr = optr;
+ size_t len = olen;
if(!len)
return CURLE_OK;
@@ -597,25 +600,30 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
}
}
- if(writeheader) {
- size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
-
- if(CURL_WRITEFUNC_PAUSE == wrote)
- /* here we pass in the HEADER bit only since if this was body as well
- then it was passed already and clearly that didn't trigger the
- pause, so this is saved for later with the HEADER bit only */
- return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
-
- if(wrote != chunklen) {
- failf(data, "Failed writing header");
- return CURLE_WRITE_ERROR;
- }
- }
-
ptr += chunklen;
len -= chunklen;
}
+ if(writeheader) {
+ size_t wrote;
+ ptr = optr;
+ len = olen;
+ Curl_set_in_callback(data, true);
+ wrote = writeheader(ptr, 1, len, data->set.writeheader);
+ Curl_set_in_callback(data, false);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ /* here we pass in the HEADER bit only since if this was body as well
+ then it was passed already and clearly that didn't trigger the
+ pause, so this is saved for later with the HEADER bit only */
+ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
+
+ if(wrote != len) {
+ failf(data, "Failed writing header");
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
return CURLE_OK;
}
@@ -657,7 +665,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
#endif /* CURL_DO_LINEEND_CONV */
}
- return Curl_client_chop_write(conn, type, ptr, len);
+ return chop_write(conn, type, ptr, len);
}
CURLcode Curl_read_plain(curl_socket_t sockfd,
@@ -798,8 +806,11 @@ static int showit(struct Curl_easy *data, curl_infotype type,
}
#endif /* CURL_DOES_CONVERSIONS */
- if(data->set.fdebug)
+ if(data->set.fdebug) {
+ Curl_set_in_callback(data, true);
rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, false);
+ }
else {
switch(type) {
case CURLINFO_TEXT:
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index fbe4f99c8..7c9134dec 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,8 +51,6 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
-CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
- size_t len) WARN_UNUSED_RESULT;
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index a5ef75c72..af53ee3ef 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -43,6 +43,7 @@
#include "sendf.h"
#include "http2.h"
#include "setopt.h"
+#include "multiif.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -361,6 +362,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.timevalue = (time_t)va_arg(param, long);
break;
+ case CURLOPT_TIMEVALUE_LARGE:
+ /*
+ * This is the value to compare with the remote document with the
+ * method set with CURLOPT_TIMECONDITION
+ */
+ data->set.timevalue = (time_t)va_arg(param, curl_off_t);
+ break;
+
case CURLOPT_SSLVERSION:
case CURLOPT_PROXY_SSLVERSION:
/*
@@ -772,11 +781,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
if(checkprefix("Set-Cookie:", argptr))
/* HTTP Header format line */
- Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+ Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL,
+ NULL);
else
/* Netscape format line */
- Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+ Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL,
+ NULL);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
free(argptr);
@@ -1028,6 +1039,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
*/
data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+#endif
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
case CURLOPT_PROXY_SERVICE_NAME:
@@ -1037,10 +1049,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
va_arg(param, char *));
break;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO)
case CURLOPT_SERVICE_NAME:
/*
* Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
@@ -1049,8 +1058,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
va_arg(param, char *));
break;
-#endif
-
case CURLOPT_HEADERDATA:
/*
* Custom pointer to pass the header write callback function
@@ -1594,6 +1601,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+ case CURLOPT_HAPROXYPROTOCOL:
+ /*
+ * Set to send the HAProxy Proxy Protocol header
+ */
+ data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
case CURLOPT_INTERFACE:
/*
* Set what interface or address/hostname to bind the socket to when
@@ -1734,7 +1748,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Set a SSL_CTX callback
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
+ if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
else
#endif
@@ -1745,7 +1759,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Set a SSL_CTX callback parameter pointer
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
+ if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
data->set.ssl.fsslctxp = va_arg(param, void *);
else
#endif
@@ -1764,7 +1778,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
- if(Curl_ssl->have_certinfo)
+ if(Curl_ssl->supports & SSLSUPP_CERTINFO)
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
else
#endif
@@ -1776,7 +1790,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
+ if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
va_arg(param, char *));
else
@@ -1789,7 +1803,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
+ if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
else
@@ -1817,7 +1831,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
+ if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
va_arg(param, char *));
@@ -1831,7 +1845,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* CA certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
+ if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
@@ -2101,6 +2115,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
break;
+ case CURLOPT_RESOLVER_START_FUNCTION:
+ /*
+ * resolver start callback function: called before a new resolver request
+ * is started
+ */
+ data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
+ break;
+
+ case CURLOPT_RESOLVER_START_DATA:
+ /*
+ * resolver start callback data pointer. Might be NULL.
+ */
+ data->set.resolver_start_client = va_arg(param, void *);
+ break;
+
case CURLOPT_CLOSESOCKETDATA:
/*
* socket callback data pointer. Might be NULL.
@@ -2524,6 +2553,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSH_COMPRESSION:
data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
break;
+ case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.happy_eyeballs_timeout = arg;
+ break;
+ case CURLOPT_DNS_SHUFFLE_ADDRESSES:
+ data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
@@ -2536,6 +2574,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
/*
* curl_easy_setopt() is the external interface for setting options on an
* easy handle.
+ *
+ * NOTE: This is one of few API functions that are allowed to be called from
+ * within a callback.
*/
#undef curl_easy_setopt
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index cd81c0254..55716c63b 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -29,9 +29,17 @@
#if defined(USE_OPENSSL)
+#include <openssl/opensslv.h>
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+#define USE_OPENSSL_SHA256
+#endif
+
+#endif
+
+#ifdef USE_OPENSSL_SHA256
/* When OpenSSL is available we use the SHA256-function from OpenSSL */
#include <openssl/sha.h>
-
#else
/* When no other crypto library is available we use this code segment */
@@ -234,7 +242,7 @@ static int SHA256_Final(unsigned char *out,
sha256_compress(md, md->buf);
md->curlen = 0;
}
- /* pad upto 56 bytes of zeroes */
+ /* pad up to 56 bytes of zeroes */
while(md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char)0;
}
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 6cb4083bb..9ac61505c 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -709,14 +709,21 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
}
/*
- * Convert a timestamp from the Windows world (100 nsec units from
- * 1 Jan 1601) to Posix time.
+ * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601)
+ * to Posix time. Cap the output to fit within a time_t.
*/
-static void get_posix_time(long *out, curl_off_t timestamp)
+static void get_posix_time(time_t *out, curl_off_t timestamp)
{
timestamp -= 116444736000000000;
timestamp /= 10000000;
- *out = (long) timestamp;
+#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
+ if(timestamp > TIME_T_MAX)
+ *out = TIME_T_MAX;
+ else if(timestamp < TIME_T_MIN)
+ *out = TIME_T_MIN;
+ else
+#endif
+ *out = (time_t) timestamp;
}
static CURLcode smb_request_state(struct connectdata *conn, bool *done)
@@ -783,10 +790,16 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
else {
smb_m = (const struct smb_nt_create_response*) msg;
conn->data->req.size = smb_swap64(smb_m->end_of_file);
- Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
- if(conn->data->set.get_filetime)
- get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
- next_state = SMB_DOWNLOAD;
+ if(conn->data->req.size < 0) {
+ req->result = CURLE_WEIRD_SERVER_REPLY;
+ next_state = SMB_CLOSE;
+ }
+ else {
+ Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
+ if(conn->data->set.get_filetime)
+ get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
+ next_state = SMB_DOWNLOAD;
+ }
}
break;
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index d9f1a854a..3f3b45a95 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -1289,6 +1289,11 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
/* Store the first recipient (or NULL if not specified) */
smtp->rcpt = data->set.mail_rcpt;
+ /* Initial data character is the first character in line: it is implicitly
+ preceded by a virtual CRLF. */
+ smtp->trailing_crlf = TRUE;
+ smtp->eob = 2;
+
/* Start the first command in the DO phase */
if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
diff --git a/Utilities/cmcurl/lib/ssh-libssh.c b/Utilities/cmcurl/lib/ssh-libssh.c
index 56775d70d..34ef490c4 100644
--- a/Utilities/cmcurl/lib/ssh-libssh.c
+++ b/Utilities/cmcurl/lib/ssh-libssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017 - 2018 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
@@ -383,8 +383,10 @@ static int myssh_is_known(struct connectdata *conn)
}
/* we don't have anything equivalent to knownkey. Always NULL */
+ Curl_set_in_callback(data, true);
rc = func(data, NULL, &foundkey, /* from the remote host */
keymatch, data->set.ssh_keyfunc_userp);
+ Curl_set_in_callback(data, false);
switch(rc) {
case CURLKHSTAT_FINE_ADD_TO_FILE:
@@ -1046,7 +1048,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
attrs = sftp_stat(sshc->sftp_session, protop->path);
if(attrs != 0) {
- data->info.filetime = (long)attrs->mtime;
+ data->info.filetime = attrs->mtime;
sftp_attributes_free(attrs);
}
@@ -1128,8 +1130,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -2421,8 +2425,7 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
ssize_t nread;
(void)sockindex;
- if(len >= (size_t)1<<32)
- len = (size_t)(1<<31)-1;
+ DEBUGASSERT(len < CURL_MAX_READ_SIZE);
switch(conn->proto.sshc.sftp_recv_state) {
case 0:
diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index a86ed706e..bf7bd54f9 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -342,6 +342,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
"SSH_AUTH_HOST",
"SSH_AUTH_KEY_INIT",
"SSH_AUTH_KEY",
+ "SSH_AUTH_GSSAPI",
"SSH_AUTH_DONE",
"SSH_SFTP_INIT",
"SSH_SFTP_REALPATH",
@@ -376,6 +377,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
"SSH_SCP_TRANS_INIT",
"SSH_SCP_UPLOAD_INIT",
"SSH_SCP_DOWNLOAD_INIT",
+ "SSH_SCP_DOWNLOAD",
"SSH_SCP_DONE",
"SSH_SCP_SEND_EOF",
"SSH_SCP_WAIT_EOF",
@@ -386,6 +388,9 @@ static void state(struct connectdata *conn, sshstate nowstate)
"QUIT"
};
+ /* a precaution to make sure the lists are in sync */
+ DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
+
if(sshc->state != nowstate) {
infof(conn->data, "SFTP %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
@@ -523,9 +528,11 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
keymatch = (enum curl_khmatch)keycheck;
/* Ask the callback how to behave */
+ Curl_set_in_callback(data, true);
rc = func(data, knownkeyp, /* from the knownhosts file */
&foundkey, /* from the remote host */
keymatch, data->set.ssh_keyfunc_userp);
+ Curl_set_in_callback(data, false);
}
else
/* no remotekey means failure! */
@@ -777,8 +784,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* This is done by simply passing sshc->rsa_pub = NULL.
*/
if(data->set.str[STRING_SSH_PUBLIC_KEY]
- /* treat empty string the same way as NULL */
- && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
+ /* treat empty string the same way as NULL */
+ && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
if(!sshc->rsa_pub)
out_of_memory = TRUE;
@@ -832,7 +839,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_AUTH_DONE);
}
else {
- char *err_msg;
+ char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
infof(data, "SSH public key authentication failed: %s\n", err_msg);
@@ -1039,7 +1046,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
if(!sshc->sftp_session) {
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
rc = LIBSSH2_ERROR_EAGAIN;
@@ -1246,7 +1253,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
+ strncasecompare(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@@ -1627,7 +1634,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc == 0) {
- data->info.filetime = (long)attrs.mtime;
+ data->info.filetime = attrs.mtime;
}
state(conn, SSH_SFTP_TRANS_INIT);
@@ -1747,8 +1754,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -1765,9 +1774,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(size_t)data->set.buffer_size :
curlx_sotouz(data->state.resume_from - passed);
- size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1,
- readthisamountnow, data->state.in);
+ size_t actuallyread;
+ Curl_set_in_callback(data, true);
+ actuallyread = data->state.fread_func(data->state.buffer, 1,
+ readthisamountnow,
+ data->state.in);
+ Curl_set_in_callback(data, false);
passed += actuallyread;
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
@@ -2131,8 +2143,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc ||
- !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
- (attrs.filesize == 0)) {
+ !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
+ (attrs.filesize == 0)) {
/*
* libssh2_sftp_open() didn't return an error, so maybe the server
* just doesn't support stat()
@@ -2264,7 +2276,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to close libssh2 file\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
@@ -2298,7 +2313,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to close libssh2 file\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
+ NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
@@ -2353,7 +2371,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->state.infilesize);
if(!sshc->ssh_channel) {
int ssh_err;
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
@@ -2407,9 +2425,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* be set in sb
*/
- /*
- * If support for >2GB files exists, use it.
- */
+ /*
+ * If support for >2GB files exists, use it.
+ */
/* get a fresh new channel from the ssh layer */
#if LIBSSH2_VERSION_NUM < 0x010700
@@ -2426,7 +2444,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(!sshc->ssh_channel) {
int ssh_err;
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
@@ -2479,7 +2497,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc) {
- infof(data, "Failed to send libssh2 channel EOF\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to send libssh2 channel EOF: %d %s\n",
+ rc, err_msg);
}
}
state(conn, SSH_SCP_WAIT_EOF);
@@ -2492,7 +2514,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc) {
- infof(data, "Failed to get channel EOF: %d\n", rc);
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
}
}
state(conn, SSH_SCP_WAIT_CLOSE);
@@ -2505,7 +2530,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc) {
- infof(data, "Channel failed to close: %d\n", rc);
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
}
}
state(conn, SSH_SCP_CHANNEL_FREE);
@@ -2518,7 +2546,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 scp subsystem\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ rc, err_msg);
}
sshc->ssh_channel = NULL;
}
@@ -2540,7 +2572,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 scp subsystem\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ rc, err_msg);
}
sshc->ssh_channel = NULL;
}
@@ -2551,7 +2587,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to disconnect libssh2 session\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect libssh2 session: %d %s\n",
+ rc, err_msg);
}
}
@@ -2576,7 +2616,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to disconnect from libssh2 agent\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect from libssh2 agent: %d %s\n",
+ rc, err_msg);
}
libssh2_agent_free(sshc->ssh_agent);
sshc->ssh_agent = NULL;
@@ -2594,7 +2638,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 session\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg);
}
sshc->ssh_session = NULL;
}
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 83a96dda1..0295d6c27 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -312,6 +312,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_HTTP2_STREAM:
return "Stream error in the HTTP/2 framing layer";
+ case CURLE_RECURSIVE_API_CALL:
+ return "API function called from within callback";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
@@ -380,6 +383,9 @@ curl_multi_strerror(CURLMcode error)
case CURLM_ADDED_ALREADY:
return "The easy handle is already added to a multi handle";
+ case CURLM_RECURSIVE_API_CALL:
+ return "API function called from within callback";
+
case CURLM_LAST:
break;
}
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index 363647737..546a3ff75 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/lib/strtoofft.c
@@ -220,8 +220,6 @@ CURLofft curlx_strtoofft(const char *str, char **endp, int base,
errno = 0;
*num = 0; /* clear by default */
- DEBUGASSERT(str);
-
while(*str && ISSPACE(*str))
str++;
if('-' == *str) {
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index 48b134ee3..d71c8e067 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -1203,8 +1203,7 @@ CURLcode telrcv(struct connectdata *conn,
CURL_SB_ACCUM(tn, c);
tn->telrcv_state = CURL_TS_SB;
}
- else
- {
+ else {
CURL_SB_ACCUM(tn, CURL_IAC);
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
@@ -1460,7 +1459,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
if(n == 0) /* no bytes */
break;
- readfile_read = (DWORD)n; /* fall thru with number of bytes read */
+ /* fall through with number of bytes read */
+ readfile_read = (DWORD)n;
}
else {
/* read from stdin */
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 20dc60040..b32960f82 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1010,7 +1010,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
state->requested_blksize = blksize;
((struct sockaddr *)&state->local_addr)->sa_family =
- (unsigned short)(conn->ip_addr->ai_family);
+ (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family);
tftp_set_timeouts(state);
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index 66f923a8e..f4bf83531 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -110,7 +110,7 @@ struct curltime Curl_now(void)
usecs /= 1000;
cnow.tv_sec = usecs / 1000000;
- cnow.tv_usec = usecs % 1000000;
+ cnow.tv_usec = (int)(usecs % 1000000);
return cnow;
}
@@ -128,7 +128,7 @@ struct curltime Curl_now(void)
struct curltime ret;
(void)gettimeofday(&now, NULL);
ret.tv_sec = now.tv_sec;
- ret.tv_usec = now.tv_usec;
+ ret.tv_usec = (int)now.tv_usec;
return ret;
}
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 8f15b1a15..131f2dc7c 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -85,7 +85,7 @@
!defined(CURL_DISABLE_IMAP)
/*
* checkheaders() checks the linked list of custom headers for a
- * particular header (prefix).
+ * particular header (prefix). Provide the prefix without colon!
*
* Returns a pointer to the first matching header or NULL if none matched.
*/
@@ -97,7 +97,8 @@ char *Curl_checkheaders(const struct connectdata *conn,
struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen) &&
+ Curl_headersep(head->data[thislen]) )
return head->data;
}
@@ -135,8 +136,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
/* this function returns a size_t, so we typecast to int to prevent warnings
with picky compilers */
+ Curl_set_in_callback(data, true);
nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
buffersize, data->state.in);
+ Curl_set_in_callback(data, false);
if(nread == CURL_READFUNC_ABORT) {
failf(data, "operation aborted by callback");
@@ -302,7 +305,9 @@ CURLcode Curl_readrewind(struct connectdata *conn)
if(data->set.seek_func) {
int err;
+ Curl_set_in_callback(data, true);
err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+ Curl_set_in_callback(data, false);
if(err) {
failf(data, "seek callback returned error %d", (int)err);
return CURLE_SEND_FAIL_REWIND;
@@ -311,8 +316,10 @@ CURLcode Curl_readrewind(struct connectdata *conn)
else if(data->set.ioctl_func) {
curlioerr err;
+ Curl_set_in_callback(data, true);
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
data->set.ioctl_client);
+ Curl_set_in_callback(data, false);
infof(data, "the ioctl callback returned %d\n", (int)err);
if(err) {
@@ -710,7 +717,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
#endif /* CURL_DISABLE_HTTP */
/* Account for body content stored in the header buffer */
- if(k->badheader && !k->ignorebody) {
+ if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
k->hbuflen));
k->bytecount += k->hbuflen;
@@ -801,10 +808,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
} /* if(!header and data to read) */
- if(conn->handler->readwrite &&
- (excess > 0 && !conn->bits.stream_was_rewound)) {
+ if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) {
/* Parse the excess data */
k->str += nread;
+
+ if(&k->str[excess] > &k->buf[data->set.buffer_size]) {
+ /* the excess amount was too excessive(!), make sure
+ it doesn't read out of buffer */
+ excess = &k->buf[data->set.buffer_size] - k->str;
+ }
nread = (ssize_t)excess;
result = conn->handler->readwrite(data, conn, &nread, &readmore);
@@ -1435,6 +1447,16 @@ static const char *find_host_sep(const char *url)
}
/*
+ * Decide in an encoding-independent manner whether a character in an
+ * URL must be escaped. The same criterion must be used in strlen_url()
+ * and strcpy_url().
+ */
+static bool urlchar_needs_escaping(int c)
+{
+ return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
+}
+
+/*
* strlen_url() returns the length of the given URL if the spaces within the
* URL were properly URL encoded.
* URL encoding should be skipped for host names, otherwise IDN resolution
@@ -1462,7 +1484,7 @@ static size_t strlen_url(const char *url, bool relative)
left = FALSE;
/* fall through */
default:
- if(*ptr >= 0x80)
+ if(urlchar_needs_escaping(*ptr))
newlen += 2;
newlen++;
break;
@@ -1507,7 +1529,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
left = FALSE;
/* fall through */
default:
- if(*iptr >= 0x80) {
+ if(urlchar_needs_escaping(*iptr)) {
snprintf(optr, 4, "%%%02x", *iptr);
optr += 3;
}
@@ -1914,7 +1936,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
char **url)
{
struct Curl_easy *data = conn->data;
-
+ bool retry = FALSE;
*url = NULL;
/* if we're talking upload, we can't do the checks below, unless the protocol
@@ -1927,7 +1949,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
conn->bits.reuse &&
(!data->set.opt_no_body
|| (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
- (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ (data->set.rtspreq != RTSPREQ_RECEIVE))
/* We got no data, we attempted to re-use a connection. For HTTP this
can be a retry so we try again regardless if we expected a body.
For other protocols we only try again only if we expected a body.
@@ -1935,6 +1957,19 @@ CURLcode Curl_retry_request(struct connectdata *conn,
This might happen if the connection was left alive when we were
done using it before, but that was closed when we wanted to read from
it again. Bad luck. Retry the same request on a fresh connect! */
+ retry = TRUE;
+ else if(data->state.refused_stream &&
+ (data->req.bytecount + data->req.headerbytecount == 0) ) {
+ /* This was sent on a refused stream, safe to rerun. A refused stream
+ error can typically only happen on HTTP/2 level if the stream is safe
+ to issue again, but the nghttp2 API can deliver the message to other
+ streams as well, which is why this adds the check the data counters
+ too. */
+ infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
+ data->state.refused_stream = FALSE; /* clear again */
+ retry = TRUE;
+ }
+ if(retry) {
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
if(!*url)
@@ -1983,11 +2018,19 @@ Curl_setup_transfer(
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- /* now copy all input parameters */
- conn->sockfd = sockindex == -1 ?
+ if(conn->bits.multiplex || conn->httpversion == 20) {
+ /* when multiplexing, the read/write sockets need to be the same! */
+ conn->sockfd = sockindex == -1 ?
+ ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
+ conn->sock[sockindex];
+ conn->writesockfd = conn->sockfd;
+ }
+ else {
+ conn->sockfd = sockindex == -1 ?
CURL_SOCKET_BAD : conn->sock[sockindex];
- conn->writesockfd = writesockindex == -1 ?
+ conn->writesockfd = writesockindex == -1 ?
CURL_SOCKET_BAD:conn->sock[writesockindex];
+ }
k->getheader = getheader;
k->size = size;
@@ -2006,10 +2049,10 @@ Curl_setup_transfer(
/* we want header and/or body, if neither then don't do this! */
if(k->getheader || !data->set.opt_no_body) {
- if(conn->sockfd != CURL_SOCKET_BAD)
+ if(sockindex != -1)
k->keepon |= KEEP_RECV;
- if(conn->writesockfd != CURL_SOCKET_BAD) {
+ if(writesockindex != -1) {
struct HTTP *http = data->req.protop;
/* HTTP 1.1 magic:
@@ -2040,7 +2083,7 @@ Curl_setup_transfer(
/* enable the write bit when we're not waiting for continue */
k->keepon |= KEEP_SEND;
}
- } /* if(conn->writesockfd != CURL_SOCKET_BAD) */
+ } /* if(writesockindex != -1) */
} /* if(k->getheader || !data->set.opt_no_body) */
}
diff --git a/Utilities/cmcurl/lib/transfer.h b/Utilities/cmcurl/lib/transfer.h
index 72526a834..9ba398d27 100644
--- a/Utilities/cmcurl/lib/transfer.h
+++ b/Utilities/cmcurl/lib/transfer.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,6 +22,7 @@
*
***************************************************************************/
+#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct connectdata *conn,
const char *thisheader);
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 74813e874..701f83ab3 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -488,25 +488,33 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->socks5_gssapi_nec = FALSE;
#endif
- /* This is our preferred CA cert bundle/path since install time */
+ /* Set the default CA cert bundle/path detected/specified at build time.
+ *
+ * If Schannel (WinSSL) is the selected SSL backend then these locations
+ * are ignored. We allow setting CA location for schannel only when
+ * explicitly specified by the user via CURLOPT_CAINFO / --cacert.
+ */
+ if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#if defined(CURL_CA_BUNDLE)
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+ if(result)
+ return result;
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
+ CURL_CA_BUNDLE);
+ if(result)
+ return result;
#endif
#if defined(CURL_CA_PATH)
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+ if(result)
+ return result;
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
+ if(result)
+ return result;
#endif
+ }
set->wildcard_enabled = FALSE;
set->chunk_bgn = ZERO_NULL;
@@ -527,6 +535,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE;
+ set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
Curl_http2_init_userset(set);
return result;
@@ -2066,15 +2075,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_URL_MALFORMAT;
}
- if(url_has_scheme && path[0] == '/' && path[1] == '/' &&
- path[2] == '/' && path[3] == '/') {
- /* This appears to be a UNC string (usually indicating a SMB share).
- * We don't do SMB in file: URLs. (TODO?)
- */
- failf(data, "SMB shares are not supported in file: URLs.");
- return CURLE_URL_MALFORMAT;
- }
-
/* Extra handling URLs with an authority component (i.e. that start with
* "file://")
*
@@ -2113,25 +2113,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
ptr += 9; /* now points to the slash after the host */
}
- /*
- * RFC 8089, Appendix D, Section D.1, says:
- *
- * > In a POSIX file system, the root of the file system is represented
- * > as a directory with a zero-length name, usually written as "/"; the
- * > presence of this root in a file URI can be taken as given by the
- * > initial slash in the "path-absolute" rule.
- *
- * i.e. the first slash is part of the path.
- *
- * However in RFC 1738 the "/" between the host (or port) and the
- * URL-path was NOT part of the URL-path. Any agent that followed the
- * older spec strictly, and wanted to refer to a file with an absolute
- * path, would have included a second slash. So if there are two
- * slashes, swallow one.
- */
- if('/' == ptr[1]) /* note: the only way ptr[0]!='/' is if ptr[1]==':' */
- ptr++;
-
/* This cannot be done with strcpy, as the memory chunks overlap! */
memmove(path, ptr, strlen(ptr) + 1);
}
@@ -2573,7 +2554,15 @@ static bool check_noproxy(const char *name, const char *no_proxy)
/* NO_PROXY was specified and it wasn't just an asterisk */
no_proxy_len = strlen(no_proxy);
- endptr = strchr(name, ':');
+ if(name[0] == '[') {
+ /* IPv6 numerical address */
+ endptr = strchr(name, ']');
+ if(!endptr)
+ return FALSE;
+ name++;
+ }
+ else
+ endptr = strchr(name, ':');
if(endptr)
namelen = endptr - name;
else
@@ -2681,13 +2670,20 @@ static char *detect_proxy(struct connectdata *conn)
prox = curl_getenv(proxy_env);
}
- if(prox)
+ envp = proxy_env;
+ if(prox) {
proxy = prox; /* use this */
+ }
else {
- proxy = curl_getenv("all_proxy"); /* default proxy to use */
- if(!proxy)
- proxy = curl_getenv("ALL_PROXY");
+ envp = (char *)"all_proxy";
+ proxy = curl_getenv(envp); /* default proxy to use */
+ if(!proxy) {
+ envp = (char *)"ALL_PROXY";
+ proxy = curl_getenv(envp);
+ }
}
+ if(proxy)
+ infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
return proxy;
}
@@ -2744,7 +2740,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
#ifdef USE_SSL
- if(!Curl_ssl->support_https_proxy)
+ if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
#endif
if(proxytype == CURLPROXY_HTTPS) {
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
@@ -2972,9 +2968,15 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
}
if(!data->set.str[STRING_NOPROXY]) {
- no_proxy = curl_getenv("no_proxy");
- if(!no_proxy)
- no_proxy = curl_getenv("NO_PROXY");
+ const char *p = "no_proxy";
+ no_proxy = curl_getenv(p);
+ if(!no_proxy) {
+ p = "NO_PROXY";
+ no_proxy = curl_getenv(p);
+ }
+ if(no_proxy) {
+ infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
+ }
}
if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
@@ -3417,7 +3419,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
* stripped off. It would be better to work directly from the original
* URL and simply replace the port part of it.
*/
- url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
+ url = aprintf("%s://%s%s%s:%d%s%s%s", conn->given->scheme,
conn->bits.ipv6_ip?"[":"", conn->host.name,
conn->bits.ipv6_ip?"]":"", conn->remote_port,
data->state.slash_removed?"/":"", data->state.path,
@@ -4116,7 +4118,7 @@ static CURLcode create_conn(struct Curl_easy *data,
*************************************************************/
if(prot_missing) {
/* We're guessing prefixes here and if we're told to use a proxy or if
- we're gonna follow a Location: later or... then we need the protocol
+ we're going to follow a Location: later or... then we need the protocol
part added so that we have a valid URL. */
char *reurl;
char *ch_lower;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 5c04ad172..7fae00fd9 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -98,6 +98,20 @@
#include "hash.h"
#include "splay.h"
+/* return the count of bytes sent, or -1 on error */
+typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *buf, /* data to write */
+ size_t len, /* max amount to write */
+ CURLcode *err); /* error to return */
+
+/* return the count of bytes read, or -1 on error */
+typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ char *buf, /* store data here */
+ size_t len, /* max amount to read */
+ CURLcode *err); /* error to return */
+
#include "mime.h"
#include "imap.h"
#include "pop3.h"
@@ -328,6 +342,7 @@ struct ntlmdata {
BYTE *output_token;
BYTE *input_token;
size_t input_token_len;
+ TCHAR *spn;
#else
unsigned int flags;
unsigned char nonce[8];
@@ -703,20 +718,6 @@ struct Curl_handler {
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
-/* return the count of bytes sent, or -1 on error */
-typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
- int sockindex, /* socketindex */
- const void *buf, /* data to write */
- size_t len, /* max amount to write */
- CURLcode *err); /* error to return */
-
-/* return the count of bytes read, or -1 on error */
-typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
- int sockindex, /* socketindex */
- char *buf, /* store data here */
- size_t len, /* max amount to read */
- CURLcode *err); /* error to return */
-
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
struct postponed_data {
char *buffer; /* Temporal store for received data during
@@ -895,7 +896,7 @@ struct connectdata {
well be the same we read from.
CURL_SOCKET_BAD disables */
- /** Dynamicly allocated strings, MUST be freed before this **/
+ /** Dynamically allocated strings, MUST be freed before this **/
/** struct is killed. **/
struct dynamically_allocated_data {
char *proxyuserpwd;
@@ -1024,10 +1025,8 @@ struct PureInfo {
int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
int httpproxycode; /* response code from proxy when received separate */
int httpversion; /* the http version number X.Y = X*10+Y */
- long filetime; /* If requested, this is might get set. Set to -1 if the time
- was unretrievable. We cannot have this of type time_t,
- since time_t is unsigned on several platforms such as
- OpenVMS. */
+ time_t filetime; /* If requested, this is might get set. Set to -1 if the
+ time was unretrievable. */
bool timecond; /* set to TRUE if the time condition didn't match, which
thus made the document NOT get fetched */
long header_size; /* size of read header(s) in bytes */
@@ -1168,7 +1167,7 @@ struct Curl_http2_dep {
};
/*
- * This struct is for holding data that was attemped to get sent to the user's
+ * This struct is for holding data that was attempted to get sent to the user's
* callback but is held due to pausing. One instance per type (BOTH, HEADER,
* BODY).
*/
@@ -1227,7 +1226,7 @@ struct UrlState {
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
-
+ bool refused_stream; /* this was refused, try again */
char *first_host; /* host name of the first (not followed) request.
if set, this should be the host name that we will
sent authorization to, no else. Used to make Location:
@@ -1424,13 +1423,8 @@ enum dupstring {
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
#endif
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
STRING_PROXY_SERVICE_NAME, /* Proxy service name */
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO) || defined(HAVE_GSSAPI)
STRING_SERVICE_NAME, /* Service name */
-#endif
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
@@ -1522,6 +1516,7 @@ struct UserDefined {
long timeout; /* in milliseconds, 0 means no timeout */
long connecttimeout; /* in milliseconds, 0 means no timeout */
long accepttimeout; /* in milliseconds, 0 means no timeout */
+ long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */
long server_response_timeout; /* in milliseconds, 0 means no timeout */
long tftp_blksize; /* in bytes, 0 means use default */
bool tftp_no_options; /* do not send TFTP options requests */
@@ -1675,13 +1670,21 @@ struct UserDefined {
bool suppress_connect_headers; /* suppress proxy CONNECT response headers
from user callbacks */
+ bool dns_shuffle_addresses; /* whether to shuffle addresses before use */
+
struct Curl_easy *stream_depends_on;
bool stream_depends_e; /* set or don't set the Exclusive bit */
int stream_weight;
+ bool haproxyprotocol; /* whether to send HAProxy PROXY protocol header */
+
struct Curl_http2_dep *stream_dependents;
bool abstract_unix_socket;
+
+ curl_resolver_start_callback resolver_start; /* optional callback called
+ before resolver start */
+ void *resolver_start_client; /* pointer to pass to resolver start callback */
};
struct Names {
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index a761ae784..5d61ce6dc 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,16 +73,10 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
ulen = strlen(userp);
plen = strlen(passwdp);
- /* Compute binary message length, checking for overflows. */
- plainlen = 2 * ulen;
- if(plainlen < ulen)
- return CURLE_OUT_OF_MEMORY;
- plainlen += plen;
- if(plainlen < plen)
- return CURLE_OUT_OF_MEMORY;
- plainlen += 2;
- if(plainlen < 2)
+ /* Compute binary message length. Check for overflows. */
+ if((ulen > SIZE_T_MAX/2) || (plen > (SIZE_T_MAX/2 - 2)))
return CURLE_OUT_OF_MEMORY;
+ plainlen = 2 * ulen + plen + 2;
plainauth = malloc(plainlen);
if(!plainauth)
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index 1b4cef486..9afb971fc 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -135,7 +135,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
}
if(!krb5->credentials) {
- /* Do we have credientials to use or are we using single sign-on? */
+ /* Do we have credentials to use or are we using single sign-on? */
if(userp && *userp) {
/* Populate our identity structure */
result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
@@ -150,12 +150,10 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
krb5->p_identity = NULL;
/* Allocate our credentials handle */
- krb5->credentials = malloc(sizeof(CredHandle));
+ krb5->credentials = calloc(1, sizeof(CredHandle));
if(!krb5->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(krb5->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
status = s_pSecFn->AcquireCredentialsHandle(NULL,
(TCHAR *)
@@ -167,11 +165,9 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- krb5->context = malloc(sizeof(CtxtHandle));
+ krb5->context = calloc(1, sizeof(CtxtHandle));
if(!krb5->context)
return CURLE_OUT_OF_MEMORY;
-
- memset(krb5->context, 0, sizeof(CtxtHandle));
}
if(chlg64 && *chlg64) {
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index 1e0d4792e..cdb8d8f0d 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -63,9 +63,9 @@
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
-#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
-#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
- (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
+#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
+#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
+ ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
#if DEBUG_ME
# define DEBUG_OUT(x) x
@@ -355,6 +355,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password.
+ * service [in] - The service type such as http, smtp, pop or imap.
+ * host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
@@ -365,6 +367,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *hostname,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
{
@@ -394,6 +398,8 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
domain are empty */
(void)userp;
(void)passwdp;
+ (void)service,
+ (void)hostname,
/* Clean up any former leftovers and initialise to defaults */
Curl_auth_ntlm_cleanup(ntlm);
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h
index f906a3c7a..1136b0f8d 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.h
+++ b/Utilities/cmcurl/lib/vauth/ntlm.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_NTLM_H
-#define HEADER_CURL_NTLM_H
+#ifndef HEADER_VAUTH_NTLM_H
+#define HEADER_VAUTH_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -140,4 +140,4 @@
#endif /* USE_NTLM */
-#endif /* HEADER_CURL_NTLM_H */
+#endif /* HEADER_VAUTH_NTLM_H */
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index e748ce3b6..089c1a6d4 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -70,6 +70,8 @@ bool Curl_auth_is_ntlm_supported(void)
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password.
+ * service [in] - The service type such as http, smtp, pop or imap.
+ * host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
@@ -80,6 +82,8 @@ bool Curl_auth_is_ntlm_supported(void)
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *host,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
{
@@ -125,12 +129,10 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
ntlm->p_identity = NULL;
/* Allocate our credentials handle */
- ntlm->credentials = malloc(sizeof(CredHandle));
+ ntlm->credentials = calloc(1, sizeof(CredHandle));
if(!ntlm->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(ntlm->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
status = s_pSecFn->AcquireCredentialsHandle(NULL,
(TCHAR *) TEXT(SP_NAME_NTLM),
@@ -141,11 +143,13 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- ntlm->context = malloc(sizeof(CtxtHandle));
+ ntlm->context = calloc(1, sizeof(CtxtHandle));
if(!ntlm->context)
return CURLE_OUT_OF_MEMORY;
- memset(ntlm->context, 0, sizeof(CtxtHandle));
+ ntlm->spn = Curl_auth_build_spn(service, host, NULL);
+ if(!ntlm->spn)
+ return CURLE_OUT_OF_MEMORY;
/* Setup the type-1 "output" security buffer */
type_1_desc.ulVersion = SECBUFFER_VERSION;
@@ -157,7 +161,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
/* Generate our type-1 message */
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
- (TCHAR *) TEXT(""),
+ ntlm->spn,
0, 0, SECURITY_NETWORK_DREP,
NULL, 0,
ntlm->context, &type_1_desc,
@@ -275,7 +279,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* Generate our type-3 message */
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
ntlm->context,
- (TCHAR *) TEXT(""),
+ ntlm->spn,
0, 0, SECURITY_NETWORK_DREP,
&type_2_desc,
0, ntlm->context,
@@ -333,6 +337,8 @@ void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
/* Reset any variables */
ntlm->token_max = 0;
+
+ Curl_safefree(ntlm->spn);
}
#endif /* USE_WINDOWS_SSPI && USE_NTLM */
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index a6797cdaf..1fe19e3f9 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -138,7 +138,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
}
if(!nego->credentials) {
- /* Do we have credientials to use or are we using single sign-on? */
+ /* Do we have credentials to use or are we using single sign-on? */
if(user && *user) {
/* Populate our identity structure */
result = Curl_create_sspi_identity(user, password, &nego->identity);
@@ -153,12 +153,10 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
nego->p_identity = NULL;
/* Allocate our credentials handle */
- nego->credentials = malloc(sizeof(CredHandle));
+ nego->credentials = calloc(1, sizeof(CredHandle));
if(!nego->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(nego->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
nego->status =
s_pSecFn->AcquireCredentialsHandle(NULL,
@@ -170,11 +168,9 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- nego->context = malloc(sizeof(CtxtHandle));
+ nego->context = calloc(1, sizeof(CtxtHandle));
if(!nego->context)
return CURLE_OUT_OF_MEMORY;
-
- memset(nego->context, 0, sizeof(CtxtHandle));
}
if(chlg64 && *chlg64) {
diff --git a/Utilities/cmcurl/lib/vauth/vauth.c b/Utilities/cmcurl/lib/vauth/vauth.c
index b995f34e2..502d443ab 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.c
+++ b/Utilities/cmcurl/lib/vauth/vauth.c
@@ -115,8 +115,8 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
* User@Domain (User Principal Name)
*
* Note: The user name may be empty when using a GSS-API library or Windows SSPI
-* as the user and domain are either obtained from the credientals cache when
-* using GSS-API or via the currently logged in user's credientals when using
+* as the user and domain are either obtained from the credentials cache when
+* using GSS-API or via the currently logged in user's credentials when using
* Windows SSPI.
*
* Parameters:
@@ -138,7 +138,7 @@ bool Curl_auth_user_contains_domain(const char *user)
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else
- /* User and domain are obtained from the GSS-API credientials cache or the
+ /* User and domain are obtained from the GSS-API credentials cache or the
currently logged in user from Windows */
valid = TRUE;
#endif
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index dfaf985c6..f43064211 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -122,6 +122,8 @@ bool Curl_auth_is_ntlm_supported(void);
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *host,
struct ntlmdata *ntlm,
char **outptr,
size_t *outlen);
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index 1752e14e8..5b0d05a15 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -399,7 +399,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
- if(Curl_ssl->support_https_proxy)
+ if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
version_info.features |= CURL_VERSION_HTTPS_PROXY;
else
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index 9294f49ed..5ed898b4f 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -703,13 +703,7 @@ static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_axtls = {
{ CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
-
- 0, /* have_ca_path */
- 0, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
-
+ 0, /* no fancy stuff */
sizeof(struct ssl_backend_data),
/*
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 46b71bfd3..20ce460e8 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -187,8 +187,13 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_0:
+#ifdef WOLFSSL_ALLOW_TLSV10
req_method = TLSv1_client_method();
use_sni(TRUE);
+#else
+ failf(data, "CyaSSL does not support TLS 1.0");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_1:
req_method = TLSv1_1_client_method();
@@ -199,8 +204,14 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_3:
+#ifdef WOLFSSL_TLS13
+ req_method = wolfTLSv1_3_client_method();
+ use_sni(TRUE);
+ break;
+#else
failf(data, "CyaSSL: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
+#endif
case CURL_SSLVERSION_SSLv3:
#ifdef WOLFSSL_ALLOW_SSLV3
req_method = SSLv3_client_method();
@@ -245,7 +256,11 @@ cyassl_connect_step1(struct connectdata *conn,
*/
if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
(wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)
+#ifdef WOLFSSL_TLS13
+ && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1)
+#endif
+ ) {
failf(data, "SSL: couldn't set the minimum protocol version");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -956,7 +971,7 @@ static CURLcode Curl_cyassl_random(struct Curl_easy *data,
return CURLE_OK;
}
-static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,
size_t unused)
@@ -966,6 +981,7 @@ static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
InitSha256(&SHA256pw);
Sha256Update(&SHA256pw, tmp, (word32)tmplen);
Sha256Final(&SHA256pw, sha256sum);
+ return CURLE_OK;
}
static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
@@ -978,15 +994,10 @@ static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_cyassl = {
{ CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
- 0, /* have_ca_path */
- 0, /* have_certinfo */
#ifdef KEEP_PEER_CERT
- 1, /* have_pinnedpubkey */
-#else
- 0, /* have_pinnedpubkey */
+ SSLSUPP_PINNEDPUBKEY |
#endif
- 1, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_SSL_CTX,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 53a7ec37b..45fe49d82 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1135,28 +1135,79 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
raise linker errors when used on that cat for some reason. */
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
- NULL, NULL, &status)) {
+ NULL, NULL, &status)) {
+ CFArrayRef items = NULL;
+
+ /* On iOS SecPKCS12Import will never add the client certificate to the
+ * Keychain.
+ *
+ * It gives us back a SecIdentityRef that we can use directly. */
+#if CURL_BUILD_IOS
const void *cKeys[] = {kSecImportExportPassphrase};
const void *cValues[] = {password};
CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
password ? 1L : 0L, NULL, NULL);
- CFArrayRef items = NULL;
- /* Here we go: */
- status = SecPKCS12Import(pkcs_data, options, &items);
- if(status == errSecSuccess && items && CFArrayGetCount(items)) {
- CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
- const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
- kSecImportItemIdentity);
+ if(options != NULL) {
+ status = SecPKCS12Import(pkcs_data, options, &items);
+ CFRelease(options);
+ }
+
+
+ /* On macOS SecPKCS12Import will always add the client certificate to
+ * the Keychain.
+ *
+ * As this doesn't match iOS, and apps may not want to see their client
+ * certificate saved in the the user's keychain, we use SecItemImport
+ * with a NULL keychain to avoid importing it.
+ *
+ * This returns a SecCertificateRef from which we can construct a
+ * SecIdentityRef.
+ */
+#elif CURL_BUILD_MAC_10_7
+ SecItemImportExportKeyParameters keyParams;
+ SecExternalFormat inputFormat = kSecFormatPKCS12;
+ SecExternalItemType inputType = kSecItemTypeCertificate;
- /* Retain the identity; we don't care about any other data... */
- CFRetain(temp_identity);
- *out_cert_and_key = (SecIdentityRef)temp_identity;
+ memset(&keyParams, 0x00, sizeof(keyParams));
+ keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ keyParams.passphrase = password;
+
+ status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
+ 0, &keyParams, NULL, &items);
+#endif
+
+
+ /* Extract the SecIdentityRef */
+ if(status == errSecSuccess && items && CFArrayGetCount(items)) {
+ CFIndex i, count;
+ count = CFArrayGetCount(items);
+
+ for(i = 0; i < count; i++) {
+ CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
+ CFTypeID itemID = CFGetTypeID(item);
+
+ if(itemID == CFDictionaryGetTypeID()) {
+ CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
+ (CFDictionaryRef) item,
+ kSecImportItemIdentity);
+ CFRetain(identity);
+ *out_cert_and_key = (SecIdentityRef) identity;
+ break;
+ }
+#if CURL_BUILD_MAC_10_7
+ else if(itemID == SecCertificateGetTypeID()) {
+ status = SecIdentityCreateWithCertificate(NULL,
+ (SecCertificateRef) item,
+ out_cert_and_key);
+ break;
+ }
+#endif
+ }
}
if(items)
CFRelease(items);
- CFRelease(options);
CFRelease(pkcs_data);
}
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
@@ -1340,7 +1391,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_BUILD_MAC */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
+ if(SSLCreateContext != NULL) { /* use the newer API if available */
if(BACKEND->ssl_ctx)
CFRelease(BACKEND->ssl_ctx);
BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
@@ -2843,13 +2894,14 @@ static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
{
assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
+ return CURLE_OK;
}
static bool Curl_darwinssl_false_start(void)
@@ -2977,15 +3029,11 @@ static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_darwinssl = {
{ CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */
- 0, /* have_ca_path */
- 0, /* have_certinfo */
#ifdef DARWIN_SSL_PINNEDPUBKEY
- 1, /* have_pinnedpubkey */
+ SSLSUPP_PINNEDPUBKEY,
#else
- 0, /* have_pinnedpubkey */
+ 0,
#endif /* DARWIN_SSL_PINNEDPUBKEY */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 8f0cc0bb8..b0856cdf4 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1353,12 +1353,8 @@ static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_gskit = {
{ CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
- 0, /* have_ca_path */
- 1, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- /* TODO: convert to 1 and fix test #1014 (if need) */
- 0, /* support_https_proxy */
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 30b255b81..207b0fd1b 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -60,15 +60,6 @@
/* The last #include file should be: */
#include "memdebug.h"
-#ifndef GNUTLS_POINTER_TO_SOCKET_CAST
-#define GNUTLS_POINTER_TO_SOCKET_CAST(p) \
- ((curl_socket_t) ((char *)(p) - (char *)NULL))
-#endif
-#ifndef GNUTLS_SOCKET_TO_POINTER_CAST
-#define GNUTLS_SOCKET_TO_POINTER_CAST(s) \
- ((void *) ((char *)NULL + (s)))
-#endif
-
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
@@ -161,7 +152,8 @@ static int gtls_mapped_sockerrno(void)
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
- ssize_t ret = swrite(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
+ curl_socket_t sock = *(curl_socket_t *)s;
+ ssize_t ret = swrite(sock, buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
@@ -171,7 +163,8 @@ static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
- ssize_t ret = sread(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
+ curl_socket_t sock = *(curl_socket_t *)s;
+ ssize_t ret = sread(sock, buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
@@ -857,7 +850,7 @@ gtls_connect_step1(struct connectdata *conn,
}
else {
/* file descriptor for the socket */
- transport_ptr = GNUTLS_SOCKET_TO_POINTER_CAST(conn->sock[sockindex]);
+ transport_ptr = &conn->sock[sockindex];
gnutls_transport_push = Curl_gtls_push;
gnutls_transport_pull = Curl_gtls_pull;
}
@@ -1770,7 +1763,7 @@ static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
@@ -1787,6 +1780,7 @@ static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
gcry_md_close(SHA256pw);
#endif
+ return CURLE_OK;
}
static bool Curl_gtls_cert_status_request(void)
@@ -1808,11 +1802,10 @@ static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_gnutls = {
{ CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 28251a388..d7759dc84 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -815,7 +815,7 @@ static void Curl_mbedtls_session_free(void *ptr)
static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
unsigned int version = mbedtls_version_get_number();
- return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
+ return snprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
(version>>16)&0xff, (version>>8)&0xff);
}
@@ -1023,13 +1023,20 @@ static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
-static void Curl_mbedtls_sha256sum(const unsigned char *input,
+static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
size_t inputlen,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
+#if MBEDTLS_VERSION_NUMBER < 0x02070000
mbedtls_sha256(input, inputlen, sha256sum, 0);
+#else
+ /* returns 0 on success, otherwise failure */
+ if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#endif
+ return CURLE_OK;
}
static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
@@ -1042,11 +1049,9 @@ static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_mbedtls = {
{ CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
- 1, /* have_ca_path */
- 0, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_SSL_CTX,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index a3ef37a12..7cd450cda 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -440,7 +440,17 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl,
PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
}
- obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
+ /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because
+ * PK11_DestroyGenericObject() does not release resources allocated by
+ * PK11_CreateGenericObject() early enough. */
+ obj =
+#ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
+ PK11_CreateManagedGenericObject
+#else
+ PK11_CreateGenericObject
+#endif
+ (slot, attrs, attr_cnt, PR_FALSE);
+
PK11_FreeSlot(slot);
if(!obj)
return result;
@@ -2304,7 +2314,7 @@ static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
@@ -2315,6 +2325,8 @@ static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
PK11_DestroyContext(SHA256pw, PR_TRUE);
+
+ return CURLE_OK;
}
static bool Curl_nss_cert_status_request(void)
@@ -2345,11 +2357,10 @@ static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_nss = {
{ CURLSSLBACKEND_NSS, "nss" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 93faa6fa8..f6a4bd3fb 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -104,13 +104,22 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */
#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */
#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */
#define CONST_EXTS const
#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1
+
+/* funny typecast define due to difference in API */
+#ifdef LIBRESSL_VERSION_NUMBER
+#define ARG2_X509_signature_print (X509_ALGOR *)
+#else
+#define ARG2_X509_signature_print
+#endif
+
#else
/* For OpenSSL before 1.1.0 */
#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
@@ -128,7 +137,8 @@ static unsigned long OpenSSL_version_num(void)
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define HAVE_X509_GET0_SIGNATURE 1
#endif
@@ -147,7 +157,7 @@ static unsigned long OpenSSL_version_num(void)
* Whether SSL_CTX_set_keylog_callback is available.
* OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
* BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
+ * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it
* lies and pretends to be OpenSSL 2.0.0).
*/
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
@@ -259,7 +269,9 @@ static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
if(!session || !keylog_file_fp)
return;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
/* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
* we have a valid SSL context if we have a non-NULL session. */
SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
@@ -649,18 +661,28 @@ int cert_stuff(struct connectdata *conn,
case SSL_FILETYPE_PKCS12:
{
- FILE *f;
- PKCS12 *p12;
+ BIO *fp = NULL;
+ PKCS12 *p12 = NULL;
EVP_PKEY *pri;
STACK_OF(X509) *ca = NULL;
- f = fopen(cert_file, "rb");
- if(!f) {
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ return 0;
+ }
+
+ if(BIO_read_filename(fp, cert_file) <= 0) {
failf(data, "could not open PKCS12 file '%s'", cert_file);
+ BIO_free(fp);
return 0;
}
- p12 = d2i_PKCS12_fp(f, NULL);
- fclose(f);
+ p12 = d2i_PKCS12_bio(fp, NULL);
+ BIO_free(fp);
if(!p12) {
failf(data, "error reading PKCS12 file '%s'", cert_file);
@@ -1311,6 +1333,51 @@ static void Curl_ossl_close_all(struct Curl_easy *data)
/* ====================================================== */
+/*
+ * Match subjectAltName against the host name. This requires a conversion
+ * in CURL_DOES_CONVERSIONS builds.
+ */
+static bool subj_alt_hostcheck(struct Curl_easy *data,
+ const char *match_pattern, const char *hostname,
+ const char *dispname)
+#ifdef CURL_DOES_CONVERSIONS
+{
+ bool res = FALSE;
+
+ /* Curl_cert_hostcheck uses host encoding, but we get ASCII from
+ OpenSSl.
+ */
+ char *match_pattern2 = strdup(match_pattern);
+
+ if(match_pattern2) {
+ if(Curl_convert_from_network(data, match_pattern2,
+ strlen(match_pattern2)) == CURLE_OK) {
+ if(Curl_cert_hostcheck(match_pattern2, hostname)) {
+ res = TRUE;
+ infof(data,
+ " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ dispname, match_pattern2);
+ }
+ }
+ free(match_pattern2);
+ }
+ else {
+ failf(data,
+ "SSL: out of memory when allocating temporary for subjectAltName");
+ }
+ return res;
+}
+#else
+{
+ if(Curl_cert_hostcheck(match_pattern, hostname)) {
+ infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ dispname, match_pattern);
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
/* Quote from RFC2818 section 3.1 "Server Identity"
@@ -1410,11 +1477,8 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
string and we cannot match it. */
- Curl_cert_hostcheck(altptr, hostname)) {
+ subj_alt_hostcheck(data, altptr, hostname, dispname)) {
dnsmatched = TRUE;
- infof(data,
- " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
- dispname, altptr);
}
break;
@@ -1725,13 +1789,40 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
case SSL3_MT_CERTIFICATE_STATUS:
return "Certificate Status";
#endif
+#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
+ case SSL3_MT_ENCRYPTED_EXTENSIONS:
+ return "Encrypted Extensions";
+#endif
+#ifdef SSL3_MT_END_OF_EARLY_DATA
+ case SSL3_MT_END_OF_EARLY_DATA:
+ return "End of early data";
+#endif
+#ifdef SSL3_MT_KEY_UPDATE
+ case SSL3_MT_KEY_UPDATE:
+ return "Key update";
+#endif
+#ifdef SSL3_MT_NEXT_PROTO
+ case SSL3_MT_NEXT_PROTO:
+ return "Next protocol";
+#endif
+#ifdef SSL3_MT_MESSAGE_HASH
+ case SSL3_MT_MESSAGE_HASH:
+ return "Message hash";
+#endif
}
}
return "Unknown";
}
-static const char *tls_rt_type(int type)
+static const char *tls_rt_type(int type, const void *buf, size_t buflen)
{
+ (void)buf;
+ (void)buflen;
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ if(type == SSL3_RT_INNER_CONTENT_TYPE && buf && buflen >= 1)
+ type = *(unsigned char *)buf;
+#endif
+
switch(type) {
#ifdef SSL3_RT_HEADER
case SSL3_RT_HEADER:
@@ -1759,10 +1850,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
void *userp)
{
struct Curl_easy *data;
- const char *msg_name, *tls_rt_name;
- char ssl_buf[1024];
char unknown[32];
- int msg_type, txt_len;
const char *verstr = NULL;
struct connectdata *conn = userp;
@@ -1810,6 +1898,10 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
}
if(ssl_ver) {
+ const char *msg_name, *tls_rt_name;
+ char ssl_buf[1024];
+ int msg_type, txt_len;
+
/* the info given when the version is zero is not that useful for us */
ssl_ver >>= 8; /* check the upper 8 bits only below */
@@ -1819,17 +1911,28 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
* is at 'buf[0]'.
*/
if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
- tls_rt_name = tls_rt_type(content_type);
+ tls_rt_name = tls_rt_type(content_type, buf, len);
else
tls_rt_name = "";
- msg_type = *(char *)buf;
- msg_name = ssl_msg_type(ssl_ver, msg_type);
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ if(content_type == SSL3_RT_INNER_CONTENT_TYPE) {
+ msg_type = 0;
+ msg_name = "[no content]";
+ }
+ else
+#endif
+ {
+ msg_type = *(char *)buf;
+ msg_name = ssl_msg_type(ssl_ver, msg_type);
+ }
txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
- Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
+ Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ }
}
Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
@@ -2082,8 +2185,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
/* it will be handled later with the context options */
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
req_method = TLS_client_method();
#else
req_method = SSLv23_client_method();
@@ -2800,7 +2902,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
ASN1_STRING *a = ASN1_STRING_new();
if(a) {
X509_get0_signature(&psig, &palg, x);
- X509_signature_print(mem, palg, a);
+ X509_signature_print(mem, ARG2_X509_signature_print palg, a);
ASN1_STRING_free(a);
if(palg) {
@@ -3035,7 +3137,8 @@ static CURLcode servercert(struct connectdata *conn,
long lerr, len;
struct Curl_easy *data = conn->data;
X509 *issuer;
- FILE *fp;
+ BIO *fp = NULL;
+ char error_buffer[256]="";
char buffer[2048];
const char *ptr;
long * const certverifyresult = SSL_IS_PROXY() ?
@@ -3046,8 +3149,20 @@ static CURLcode servercert(struct connectdata *conn,
/* we've been asked to gather certificate info! */
(void)get_cert_chain(conn, connssl);
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ BIO_free(mem);
+ return 0;
+ }
+
BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
if(!BACKEND->server_cert) {
+ BIO_free(fp);
BIO_free(mem);
if(!strict)
return CURLE_OK;
@@ -3077,6 +3192,7 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifyhost)) {
result = verifyhost(conn, BACKEND->server_cert);
if(result) {
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
@@ -3098,35 +3214,35 @@ static CURLcode servercert(struct connectdata *conn,
/* e.g. match issuer name with provided issuer certificate */
if(SSL_SET_OPTION(issuercert)) {
- fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
- if(!fp) {
+ if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
SSL_SET_OPTION(issuercert));
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
- issuer = PEM_read_X509(fp, NULL, ZERO_NULL, NULL);
+ issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL);
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
+ BIO_free(fp);
X509_free(issuer);
- fclose(fp);
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
- fclose(fp);
-
if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
+ BIO_free(fp);
X509_free(issuer);
+ X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
@@ -3161,6 +3277,7 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl);
if(result) {
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
@@ -3180,6 +3297,7 @@ static CURLcode servercert(struct connectdata *conn,
failf(data, "SSL: public key does not match pinned public key!");
}
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
connssl->connecting_state = ssl_connect_done;
@@ -3580,25 +3698,34 @@ static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
unsigned char *md5sum /* output */,
size_t unused)
{
- MD5_CTX MD5pw;
- (void)unused;
- MD5_Init(&MD5pw);
- MD5_Update(&MD5pw, tmp, tmplen);
- MD5_Final(md5sum, &MD5pw);
+ EVP_MD_CTX *mdctx;
+ unsigned int len = 0;
+ (void) unused;
+
+ mdctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
+ EVP_DigestUpdate(mdctx, tmp, tmplen);
+ EVP_DigestFinal_ex(mdctx, md5sum, &len);
+ EVP_MD_CTX_destroy(mdctx);
return CURLE_OK;
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,
size_t unused)
{
- SHA256_CTX SHA256pw;
- (void)unused;
- SHA256_Init(&SHA256pw);
- SHA256_Update(&SHA256pw, tmp, tmplen);
- SHA256_Final(sha256sum, &SHA256pw);
+ EVP_MD_CTX *mdctx;
+ unsigned int len = 0;
+ (void) unused;
+
+ mdctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
+ EVP_DigestUpdate(mdctx, tmp, tmplen);
+ EVP_DigestFinal_ex(mdctx, sha256sum, &len);
+ EVP_MD_CTX_destroy(mdctx);
+ return CURLE_OK;
}
#endif
@@ -3623,11 +3750,11 @@ static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_openssl = {
{ CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_SSL_CTX |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
index df29fa945..604cb4c86 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -620,12 +620,10 @@ polarssl_connect_step3(struct connectdata *conn,
ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- our_ssl_sessionid = malloc(sizeof(ssl_session));
+ our_ssl_sessionid = calloc(1, sizeof(ssl_session));
if(!our_ssl_sessionid)
return CURLE_OUT_OF_MEMORY;
- memset(our_ssl_sessionid, 0, sizeof(ssl_session));
-
ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
failf(data, "ssl_get_session returned -0x%x", -ret);
@@ -882,13 +880,14 @@ static bool Curl_polarssl_data_pending(const struct connectdata *conn,
return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
-static void Curl_polarssl_sha256sum(const unsigned char *input,
+static CURLcode Curl_polarssl_sha256sum(const unsigned char *input,
size_t inputlen,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
sha256(input, inputlen, sha256sum, 0);
+ return CURLE_OK;
}
static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
@@ -901,11 +900,8 @@ static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_polarssl = {
{ CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
- 1, /* have_ca_path */
- 0, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 85c64cf44..2cfd5c19f 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,13 +42,12 @@
#ifdef USE_SCHANNEL
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
#ifndef USE_WINDOWS_SSPI
# error "Can't compile SCHANNEL support without SSPI."
#endif
-#include <schnlsp.h>
-#include <schannel.h>
-#include "curl_sspi.h"
#include "schannel.h"
#include "vtls.h"
#include "sendf.h"
@@ -61,7 +60,6 @@
#include "x509asn1.h"
#include "curl_printf.h"
#include "system_win32.h"
-#include "hostcheck.h"
/* The last #include file should be: */
#include "curl_memory.h"
@@ -92,6 +90,12 @@
#endif
#endif
+#ifdef UNICODE
+#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
+#else
+#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A
+#endif
+
#ifndef SP_PROT_SSL2_CLIENT
#define SP_PROT_SSL2_CLIENT 0x00000008
#endif
@@ -124,50 +128,25 @@
#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+#define CERT_THUMBPRINT_STR_LEN 40
+#define CERT_THUMBPRINT_DATA_LEN 20
+
/* Uncomment to force verbose output
* #define infof(x, y, ...) printf(y, __VA_ARGS__)
* #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/
-/* Structs to store Schannel handles */
-struct curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- int refcount;
-};
-
-struct curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-
-struct ssl_backend_data {
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another Curl_read_plain (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool use_alpn; /* true if ALPN is used for this connection */
-};
+#ifndef CALG_SHA_256
+# define CALG_SHA_256 0x0000800c
+#endif
#define BACKEND connssl->backend
static Curl_recv schannel_recv;
static Curl_send schannel_send;
-#ifdef _WIN32_WCE
-static CURLcode verify_certificate(struct connectdata *conn, int sockindex);
-#endif
+static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+ const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
void *BufDataPtr, unsigned long BufByteSize)
@@ -221,6 +200,56 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
}
static CURLcode
+get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
+ TCHAR **thumbprint)
+{
+ TCHAR *sep;
+ size_t store_name_len;
+
+ sep = _tcschr(path, TEXT('\\'));
+ if(sep == NULL)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ store_name_len = sep - path;
+
+ if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_USER;
+ else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE;
+ else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE;
+ else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_SERVICES;
+ else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_USERS;
+ else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
+ else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
+ else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
+ else
+ return CURLE_SSL_CONNECT_ERROR;
+
+ *store_path = sep + 1;
+
+ sep = _tcschr(*store_path, TEXT('\\'));
+ if(sep == NULL)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ *sep = 0;
+
+ *thumbprint = sep + 1;
+ if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ return CURLE_OK;
+}
+
+static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
{
ssize_t written = -1;
@@ -234,6 +263,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
unsigned char alpn_buffer[128];
#endif
SCHANNEL_CRED schannel_cred;
+ PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
struct curl_schannel_cred *old_cred = NULL;
struct in_addr addr;
@@ -268,6 +298,26 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
BACKEND->use_alpn = false;
#endif
+#ifdef _WIN32_WCE
+ /* certificate validation on CE doesn't seem to work right; we'll
+ * do it following a more manual process. */
+ BACKEND->use_manual_cred_validation = true;
+#else
+ if(SSL_CONN_CONFIG(CAfile)) {
+ if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ BACKEND->use_manual_cred_validation = true;
+ }
+ else {
+ failf(data, "schannel: this version of Windows is too old to support "
+ "certificate verification via CA bundle file.");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ BACKEND->use_manual_cred_validation = false;
+#endif
+
BACKEND->cred = NULL;
/* check for an existing re-usable credential handle */
@@ -291,26 +341,23 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
if(conn->ssl_config.verifypeer) {
-#ifdef _WIN32_WCE
- /* certificate validation on CE doesn't seem to work right; we'll
- do it following a more manual process. */
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
- SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
-#else
- schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+ if(BACKEND->use_manual_cred_validation)
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
+ else
+ schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+
/* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
- if(data->set.ssl.no_revoke)
+ if(data->set.ssl.no_revoke) {
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
- else
- schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
-#endif
- if(data->set.ssl.no_revoke)
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+
infof(data, "schannel: disabled server certificate revocation "
"checks\n");
- else
+ }
+ else {
+ schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
infof(data, "schannel: checking server certificate revocation\n");
+ }
}
else {
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
@@ -354,14 +401,70 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
+ /* client certificate */
+ if(data->set.ssl.cert) {
+ DWORD cert_store_name;
+ TCHAR *cert_store_path;
+ TCHAR *cert_thumbprint_str;
+ CRYPT_HASH_BLOB cert_thumbprint;
+ BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
+ HCERTSTORE cert_store;
+
+ TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert);
+ if(!cert_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = get_cert_location(cert_path, &cert_store_name,
+ &cert_store_path, &cert_thumbprint_str);
+ if(result != CURLE_OK) {
+ Curl_unicodefree(cert_path);
+ return result;
+ }
+
+ cert_store = CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+ (HCRYPTPROV)NULL,
+ cert_store_name, cert_store_path);
+ if(!cert_store) {
+ Curl_unicodefree(cert_path);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ cert_thumbprint.pbData = cert_thumbprint_data;
+ cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
+
+ if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN,
+ CRYPT_STRING_HEX,
+ cert_thumbprint_data, &cert_thumbprint.cbData,
+ NULL, NULL)) {
+ Curl_unicodefree(cert_path);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ client_certs[0] = CertFindCertificateInStore(
+ cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_HASH, &cert_thumbprint, NULL);
+
+ Curl_unicodefree(cert_path);
+
+ if(client_certs[0]) {
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+
+ CertCloseStore(cert_store, 0);
+ }
+
/* allocate memory for the re-usable credential handle */
BACKEND->cred = (struct curl_schannel_cred *)
- malloc(sizeof(struct curl_schannel_cred));
+ calloc(1, sizeof(struct curl_schannel_cred));
if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
+
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
return CURLE_OUT_OF_MEMORY;
}
- memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
@@ -373,6 +476,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
&BACKEND->cred->cred_handle,
&BACKEND->cred->time_stamp);
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed: %s",
@@ -438,8 +544,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
- else
- {
+ else {
InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
@@ -459,12 +564,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
/* allocate memory for the security context handle */
BACKEND->ctxt = (struct curl_schannel_ctxt *)
- malloc(sizeof(struct curl_schannel_ctxt));
+ calloc(1, sizeof(struct curl_schannel_ctxt));
if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt));
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
@@ -542,6 +646,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
bool doread;
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+ const char *pubkey_ptr;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -761,12 +866,20 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS handshake complete\n");
}
-#ifdef _WIN32_WCE
- /* Windows CE doesn't do any server certificate validation.
- We have to do it manually. */
- if(conn->ssl_config.verifypeer)
+ pubkey_ptr = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ if(pubkey_ptr) {
+ result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ return result;
+ }
+ }
+
+ if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
return verify_certificate(conn, sockindex);
-#endif
+ }
return CURLE_OK;
}
@@ -1669,145 +1782,136 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-#ifdef _WIN32_WCE
-static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+ const char *pinnedpubkey)
{
SECURITY_STATUS status;
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- CURLcode result = CURLE_OK;
CERT_CONTEXT *pCertContextServer = NULL;
- const CERT_CHAIN_CONTEXT *pChainContext = NULL;
- const char * const conn_hostname = SSL_IS_PROXY() ?
- conn->http_proxy.host.name :
- conn->host.name;
+ const char *x509_der;
+ DWORD x509_der_len;
+ curl_X509certificate x509_parsed;
+ curl_asn1Element *pubkey;
- status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
- SECPKG_ATTR_REMOTE_CERT_CONTEXT,
- &pCertContextServer);
+ /* Result is returned to caller */
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
- failf(data, "schannel: Failed to read remote certificate context: %s",
- Curl_sspi_strerror(conn, status));
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ /* if a path wasn't specified, don't pin */
+ if(!pinnedpubkey)
+ return CURLE_OK;
- if(result == CURLE_OK) {
- CERT_CHAIN_PARA ChainPara;
- memset(&ChainPara, 0, sizeof(ChainPara));
- ChainPara.cbSize = sizeof(ChainPara);
-
- if(!CertGetCertificateChain(NULL,
- pCertContextServer,
- NULL,
- pCertContextServer->hCertStore,
- &ChainPara,
- (data->set.ssl.no_revoke ? 0 :
- CERT_CHAIN_REVOCATION_CHECK_CHAIN),
- NULL,
- &pChainContext)) {
- failf(data, "schannel: CertGetCertificateChain failed: %s",
- Curl_sspi_strerror(conn, GetLastError()));
- pChainContext = NULL;
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ do {
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
- if(result == CURLE_OK) {
- CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
- DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
- dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
- if(dwTrustErrorMask) {
- if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_REVOKED");
- else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_PARTIAL_CHAIN");
- else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_UNTRUSTED_ROOT");
- else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_NOT_TIME_VALID");
- else
- failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
- dwTrustErrorMask);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ break; /* failed */
}
- }
- if(result == CURLE_OK) {
- if(conn->ssl_config.verifyhost) {
- TCHAR cert_hostname_buff[256];
- DWORD len;
-
- /* TODO: Fix this for certificates with multiple alternative names.
- Right now we're only asking for the first preferred alternative name.
- Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
- (if WinCE supports that?) and run this section in a loop for each.
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx
- curl: (51) schannel: CertGetNameString() certificate hostname
- (.google.com) did not match connection (google.com)
- */
- len = CertGetNameString(pCertContextServer,
- CERT_NAME_DNS_TYPE,
- CERT_NAME_DISABLE_IE4_UTF8_FLAG,
- NULL,
- cert_hostname_buff,
- 256);
- if(len > 0) {
- const char *cert_hostname;
-
- /* Comparing the cert name and the connection hostname encoded as UTF-8
- * is acceptable since both values are assumed to use ASCII
- * (or some equivalent) encoding
- */
- cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff);
- if(!cert_hostname) {
- result = CURLE_OUT_OF_MEMORY;
- }
- else{
- int match_result;
-
- match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name);
- if(match_result == CURL_HOST_MATCH) {
- infof(data,
- "schannel: connection hostname (%s) validated "
- "against certificate name (%s)\n",
- conn->host.name,
- cert_hostname);
- result = CURLE_OK;
- }
- else{
- failf(data,
- "schannel: connection hostname (%s) "
- "does not match certificate name (%s)",
- conn->host.name,
- cert_hostname);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- Curl_unicodefree(cert_hostname);
- }
- }
- else {
- failf(data,
- "schannel: CertGetNameString did not provide any "
- "certificate name information");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+
+ if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
+ (pCertContextServer->cbCertEncoded > 0)))
+ break;
+
+ x509_der = (const char *)pCertContextServer->pbCertEncoded;
+ x509_der_len = pCertContextServer->cbCertEncoded;
+ memset(&x509_parsed, 0, sizeof x509_parsed);
+ if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+ break;
+
+ pubkey = &x509_parsed.subjectPublicKeyInfo;
+ if(!pubkey->header || pubkey->end <= pubkey->header) {
+ failf(data, "SSL: failed retrieving public key from server certificate");
+ break;
}
- }
- if(pChainContext)
- CertFreeCertificateChain(pChainContext);
+ result = Curl_pin_peer_pubkey(data,
+ pinnedpubkey,
+ (const unsigned char *)pubkey->header,
+ (size_t)(pubkey->end - pubkey->header));
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ }
+ } while(0);
if(pCertContextServer)
CertFreeCertificateContext(pCertContextServer);
return result;
}
-#endif /* _WIN32_WCE */
+
+static void Curl_schannel_checksum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *checksum,
+ size_t checksumlen,
+ DWORD provType,
+ const unsigned int algId)
+{
+ HCRYPTPROV hProv = 0;
+ HCRYPTHASH hHash = 0;
+ DWORD cbHashSize = 0;
+ DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
+ DWORD dwChecksumLen = (DWORD)checksumlen;
+
+ /* since this can fail in multiple ways, zero memory first so we never
+ * return old data
+ */
+ memset(checksum, 0, checksumlen);
+
+ if(!CryptAcquireContext(&hProv, NULL, NULL, provType,
+ CRYPT_VERIFYCONTEXT))
+ return; /* failed */
+
+ do {
+ if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
+ break; /* failed */
+
+ if(!CryptHashData(hHash, (const BYTE*)input, (DWORD)inputlen, 0))
+ break; /* failed */
+
+ /* get hash size */
+ if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize,
+ &dwHashSizeLen, 0))
+ break; /* failed */
+
+ /* check hash size */
+ if(checksumlen < cbHashSize)
+ break; /* failed */
+
+ if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0))
+ break; /* failed */
+ } while(0);
+
+ if(hHash)
+ CryptDestroyHash(hHash);
+
+ if(hProv)
+ CryptReleaseContext(hProv, 0);
+}
+
+static CURLcode Curl_schannel_md5sum(unsigned char *input,
+ size_t inputlen,
+ unsigned char *md5sum,
+ size_t md5len)
+{
+ Curl_schannel_checksum(input, inputlen, md5sum, md5len,
+ PROV_RSA_FULL, CALG_MD5);
+ return CURLE_OK;
+}
+
+static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len)
+{
+ Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
+ PROV_RSA_AES, CALG_SHA_256);
+ return CURLE_OK;
+}
static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
@@ -1819,11 +1923,8 @@ static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
- 0, /* have_ca_path */
- 1, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
@@ -1845,8 +1946,8 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- NULL /* sha256sum */
+ Curl_schannel_md5sum, /* md5sum */
+ Curl_schannel_sha256sum /* sha256sum */
};
#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 932103da4..447690027 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -26,9 +26,49 @@
#ifdef USE_SCHANNEL
+#include <schnlsp.h>
+#include <schannel.h>
+#include "curl_sspi.h"
+
#include "urldata.h"
extern const struct Curl_ssl Curl_ssl_schannel;
+CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+
+/* structs to expose only in schannel.c and schannel_verify.c */
+#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
+ bool use_manual_cred_validation; /* true if manual cred validation is used */
+};
+#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
+
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
new file mode 100644
index 000000000..db187dd6b
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -0,0 +1,551 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for SChannel-specific certificate verification. This code should
+ * only be invoked by code in schannel.c.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
+#ifndef USE_WINDOWS_SSPI
+# error "Can't compile SCHANNEL support without SSPI."
+#endif
+
+#include "schannel.h"
+#include "vtls.h"
+#include "sendf.h"
+#include "strerror.h"
+#include "curl_multibyte.h"
+#include "curl_printf.h"
+#include "hostcheck.h"
+#include "system_win32.h"
+
+/* The last #include file should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define BACKEND connssl->backend
+
+#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
+#define BEGIN_CERT "-----BEGIN CERTIFICATE-----\n"
+#define END_CERT "\n-----END CERTIFICATE-----"
+
+typedef struct {
+ DWORD cbSize;
+ HCERTSTORE hRestrictedRoot;
+ HCERTSTORE hRestrictedTrust;
+ HCERTSTORE hRestrictedOther;
+ DWORD cAdditionalStore;
+ HCERTSTORE *rghAdditionalStore;
+ DWORD dwFlags;
+ DWORD dwUrlRetrievalTimeout;
+ DWORD MaximumCachedCertificates;
+ DWORD CycleDetectionModulus;
+ HCERTSTORE hExclusiveRoot;
+ HCERTSTORE hExclusiveTrustedPeople;
+} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
+
+
+static CURLcode add_certs_to_store(HCERTSTORE trust_store,
+ const char *ca_file,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ struct Curl_easy *data = conn->data;
+ HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
+ LARGE_INTEGER file_size;
+ char *ca_file_buffer = NULL;
+ char *current_ca_file_ptr = NULL;
+ const TCHAR *ca_file_tstr = NULL;
+ size_t ca_file_bufsize = 0;
+ DWORD total_bytes_read = 0;
+ bool more_certs = 0;
+ int num_certs = 0;
+ size_t END_CERT_LEN;
+
+ ca_file_tstr = Curl_convert_UTF8_to_tchar(ca_file);
+ if(!ca_file_tstr) {
+ failf(data,
+ "schannel: invalid path name for CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ /*
+ * Read the CA file completely into memory before parsing it. This
+ * optimizes for the common case where the CA file will be relatively
+ * small ( < 1 MiB ).
+ */
+ ca_file_handle = CreateFile(ca_file_tstr,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if(ca_file_handle == INVALID_HANDLE_VALUE) {
+ failf(data,
+ "schannel: failed to open CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ if(!GetFileSizeEx(ca_file_handle, &file_size)) {
+ failf(data,
+ "schannel: failed to determine size of CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ if(file_size.QuadPart > MAX_CAFILE_SIZE) {
+ failf(data,
+ "schannel: CA file exceeds max size of %u bytes",
+ MAX_CAFILE_SIZE);
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ ca_file_bufsize = (size_t)file_size.QuadPart;
+ ca_file_buffer = (char *)malloc(ca_file_bufsize + 1);
+ if(!ca_file_buffer) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ result = CURLE_OK;
+ while(total_bytes_read < ca_file_bufsize) {
+ DWORD bytes_to_read = (DWORD)(ca_file_bufsize - total_bytes_read);
+ DWORD bytes_read = 0;
+
+ if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read,
+ bytes_to_read, &bytes_read, NULL)) {
+
+ failf(data,
+ "schannel: failed to read from CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+ if(bytes_read == 0) {
+ /* Premature EOF -- adjust the bufsize to the new value */
+ ca_file_bufsize = total_bytes_read;
+ }
+ else {
+ total_bytes_read += bytes_read;
+ }
+ }
+
+ /* Null terminate the buffer */
+ ca_file_buffer[ca_file_bufsize] = '\0';
+
+ if(result != CURLE_OK) {
+ goto cleanup;
+ }
+
+ END_CERT_LEN = strlen(END_CERT);
+
+ more_certs = 1;
+ current_ca_file_ptr = ca_file_buffer;
+ while(more_certs && *current_ca_file_ptr != '\0') {
+ char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT);
+ if(!begin_cert_ptr) {
+ more_certs = 0;
+ }
+ else {
+ char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT);
+ if(!end_cert_ptr) {
+ failf(data,
+ "schannel: CA file '%s' is not correctly formatted",
+ ca_file);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ CERT_BLOB cert_blob;
+ CERT_CONTEXT *cert_context = NULL;
+ BOOL add_cert_result = FALSE;
+ DWORD actual_content_type = 0;
+ DWORD cert_size = (DWORD)
+ ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr);
+
+ cert_blob.pbData = (BYTE *)begin_cert_ptr;
+ cert_blob.cbData = cert_size;
+ if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
+ &cert_blob,
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_ALL,
+ 0,
+ NULL,
+ &actual_content_type,
+ NULL,
+ NULL,
+ NULL,
+ &cert_context)) {
+
+ failf(data,
+ "schannel: failed to extract certificate from CA file "
+ "'%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ current_ca_file_ptr = begin_cert_ptr + cert_size;
+
+ /* Sanity check that the cert_context object is the right type */
+ if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
+ failf(data,
+ "schannel: unexpected content type '%d' when extracting "
+ "certificate from CA file '%s'",
+ actual_content_type, ca_file);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ add_cert_result =
+ CertAddCertificateContextToStore(trust_store,
+ cert_context,
+ CERT_STORE_ADD_ALWAYS,
+ NULL);
+ CertFreeCertificateContext(cert_context);
+ if(!add_cert_result) {
+ failf(data,
+ "schannel: failed to add certificate from CA file '%s'"
+ "to certificate store: %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ num_certs++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(!num_certs) {
+ infof(data,
+ "schannel: did not add any certificates from CA file '%s'\n",
+ ca_file);
+ }
+ else {
+ infof(data,
+ "schannel: added %d certificate(s) from CA file '%s'\n",
+ num_certs, ca_file);
+ }
+ }
+
+cleanup:
+ if(ca_file_handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(ca_file_handle);
+ }
+ Curl_safefree(ca_file_buffer);
+ Curl_unicodefree(ca_file_tstr);
+
+ return result;
+}
+
+static CURLcode verify_host(struct Curl_easy *data,
+ CERT_CONTEXT *pCertContextServer,
+ const char * const conn_hostname)
+{
+ CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
+ TCHAR *cert_hostname_buff = NULL;
+ size_t cert_hostname_buff_index = 0;
+ DWORD len = 0;
+ DWORD actual_len = 0;
+
+ /* CertGetNameString will provide the 8-bit character string without
+ * any decoding */
+ DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG;
+
+#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
+ name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG;
+#endif
+
+ /* Determine the size of the string needed for the cert hostname */
+ len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ NULL,
+ 0);
+ if(len == 0) {
+ failf(data,
+ "schannel: CertGetNameString() returned no "
+ "certificate name information");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto cleanup;
+ }
+
+ /* CertGetNameString guarantees that the returned name will not contain
+ * embedded null bytes. This appears to be undocumented behavior.
+ */
+ cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR));
+ actual_len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ (LPTSTR) cert_hostname_buff,
+ len);
+
+ /* Sanity check */
+ if(actual_len != len) {
+ failf(data,
+ "schannel: CertGetNameString() returned certificate "
+ "name information of unexpected size");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto cleanup;
+ }
+
+ /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output
+ * will contain all DNS names, where each name is null-terminated
+ * and the last DNS name is double null-terminated. Due to this
+ * encoding, use the length of the buffer to iterate over all names.
+ */
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ while(cert_hostname_buff_index < len &&
+ cert_hostname_buff[cert_hostname_buff_index] != TEXT('\0') &&
+ result == CURLE_PEER_FAILED_VERIFICATION) {
+
+ char *cert_hostname;
+
+ /* Comparing the cert name and the connection hostname encoded as UTF-8
+ * is acceptable since both values are assumed to use ASCII
+ * (or some equivalent) encoding
+ */
+ cert_hostname = Curl_convert_tchar_to_UTF8(
+ &cert_hostname_buff[cert_hostname_buff_index]);
+ if(!cert_hostname) {
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ int match_result;
+
+ match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname);
+ if(match_result == CURL_HOST_MATCH) {
+ infof(data,
+ "schannel: connection hostname (%s) validated "
+ "against certificate name (%s)\n",
+ conn_hostname, cert_hostname);
+ result = CURLE_OK;
+ }
+ else {
+ size_t cert_hostname_len;
+
+ infof(data,
+ "schannel: connection hostname (%s) did not match "
+ "against certificate name (%s)\n",
+ conn_hostname, cert_hostname);
+
+ cert_hostname_len = _tcslen(
+ &cert_hostname_buff[cert_hostname_buff_index]);
+
+ /* Move on to next cert name */
+ cert_hostname_buff_index += cert_hostname_len + 1;
+
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ Curl_unicodefree(cert_hostname);
+ }
+ }
+
+ if(result == CURLE_PEER_FAILED_VERIFICATION) {
+ failf(data,
+ "schannel: CertGetNameString() failed to match "
+ "connection hostname (%s) against server certificate names",
+ conn_hostname);
+ }
+ else if(result != CURLE_OK)
+ failf(data, "schannel: server certificate name verification failed");
+
+cleanup:
+ Curl_unicodefree(cert_hostname_buff);
+
+ return result;
+}
+
+CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+{
+ SECURITY_STATUS status;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result = CURLE_OK;
+ CERT_CONTEXT *pCertContextServer = NULL;
+ const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+ HCERTCHAINENGINE cert_chain_engine = NULL;
+ HCERTSTORE trust_store = NULL;
+ const char * const conn_hostname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.name :
+ conn->host.name;
+
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
+
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) &&
+ BACKEND->use_manual_cred_validation) {
+ /*
+ * Create a chain engine that uses the certificates in the CA file as
+ * trusted certificates. This is only supported on Windows 7+.
+ */
+
+ if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) {
+ failf(data, "schannel: this version of Windows is too old to support "
+ "certificate verification via CA bundle file.");
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Open the certificate store */
+ trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(!trust_store) {
+ failf(data, "schannel: failed to create certificate store: %s",
+ Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
+ conn);
+ }
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_ENGINE_CONFIG_WIN7 engine_config;
+ BOOL create_engine_result;
+
+ memset(&engine_config, 0, sizeof(engine_config));
+ engine_config.cbSize = sizeof(engine_config);
+ engine_config.hExclusiveRoot = trust_store;
+
+ /* CertCreateCertificateChainEngine will check the expected size of the
+ * CERT_CHAIN_ENGINE_CONFIG structure and fail if the specified size
+ * does not match the expected size. When this occurs, it indicates that
+ * CAINFO is not supported on the version of Windows in use.
+ */
+ create_engine_result =
+ CertCreateCertificateChainEngine(
+ (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine);
+ if(!create_engine_result) {
+ failf(data,
+ "schannel: failed to create certificate chain engine: %s",
+ Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_PARA ChainPara;
+
+ memset(&ChainPara, 0, sizeof(ChainPara));
+ ChainPara.cbSize = sizeof(ChainPara);
+
+ if(!CertGetCertificateChain(cert_chain_engine,
+ pCertContextServer,
+ NULL,
+ pCertContextServer->hCertStore,
+ &ChainPara,
+ (data->set.ssl.no_revoke ? 0 :
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN),
+ NULL,
+ &pChainContext)) {
+ failf(data, "schannel: CertGetCertificateChain failed: %s",
+ Curl_sspi_strerror(conn, GetLastError()));
+ pChainContext = NULL;
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
+ DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
+ dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
+ if(dwTrustErrorMask) {
+ if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_REVOKED");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_PARTIAL_CHAIN");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_UNTRUSTED_ROOT");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_NOT_TIME_VALID");
+ else if(dwTrustErrorMask & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_REVOCATION_STATUS_UNKNOWN");
+ else
+ failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+ dwTrustErrorMask);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
+ result = verify_host(conn->data, pCertContextServer, conn_hostname);
+ }
+ }
+
+ if(cert_chain_engine) {
+ CertFreeCertificateChainEngine(cert_chain_engine);
+ }
+
+ if(trust_store) {
+ CertCloseStore(trust_store, 0);
+ }
+
+ if(pChainContext)
+ CertFreeCertificateChain(pChainContext);
+
+ if(pCertContextServer)
+ CertFreeCertificateContext(pCertContextServer);
+
+ return result;
+}
+
+#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index def1d30cb..ee5bc7a0a 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -211,7 +211,7 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
!conn->proxy_ssl[sockindex].use) {
struct ssl_backend_data *pbdata;
- if(!Curl_ssl->support_https_proxy)
+ if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
return CURLE_NOT_BUILT_IN;
/* The pointers to the ssl backend data, which is opaque here, are swapped
@@ -511,7 +511,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
- defined(USE_MBEDTLS)
+ defined(USE_MBEDTLS) || defined(USE_CYASSL)
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
@@ -831,8 +831,12 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
- Curl_ssl->sha256sum(pubkey, pubkeylen,
+ encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
+
+ if(encode != CURLE_OK)
+ return encode;
+
encode = Curl_base64_encode(data, (char *)sha256sumdigest,
CURL_SHA256_DIGEST_LENGTH, &encoded,
&encodedlen);
@@ -1127,13 +1131,7 @@ static void Curl_multissl_close(struct connectdata *conn, int sockindex)
static const struct Curl_ssl Curl_ssl_multi = {
{ CURLSSLBACKEND_NONE, "multi" }, /* info */
-
- 0, /* have_ca_path */
- 0, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
-
+ 0, /* supports nothing */
(size_t)-1, /* something insanely large to be on the safe side */
Curl_multissl_init, /* init */
@@ -1300,6 +1298,9 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
{
int i;
+ if(avail)
+ *avail = (const curl_ssl_backend **)&available_backends;
+
if(Curl_ssl != &Curl_ssl_multi)
return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
@@ -1311,8 +1312,6 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
}
}
- if(avail)
- *avail = (const curl_ssl_backend **)&available_backends;
return CURLSSLSET_UNKNOWN_BACKEND;
}
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index c5f9d4a3f..e7b87c4d3 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,20 +26,19 @@
struct connectdata;
struct ssl_connect_data;
+#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */
+#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */
+#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */
+#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */
+#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */
+
struct Curl_ssl {
/*
* This *must* be the first entry to allow returning the list of available
* backends in curl_global_sslset().
*/
curl_ssl_backend info;
-
- unsigned have_ca_path:1; /* supports CAPATH */
- unsigned have_certinfo:1; /* supports CURLOPT_CERTINFO */
- unsigned have_pinnedpubkey:1; /* supports CURLOPT_PINNEDPUBLICKEY */
- unsigned have_ssl_ctx:1; /* supports CURLOPT_SSL_CTX_* */
-
- unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
-
+ unsigned int supports; /* bitfield, see above */
size_t sizeof_ssl_backend_data;
int (*init)(void);
@@ -72,7 +71,7 @@ struct Curl_ssl {
CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
unsigned char *md5sum, size_t md5sumlen);
- void (*sha256sum)(const unsigned char *input, size_t inputlen,
+ CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
};
@@ -113,8 +112,10 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
#endif
#ifndef MD5_DIGEST_LENGTH
+#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
+#endif
#ifndef CURL_SHA256_DIGEST_LENGTH
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index ab6d29998..f6a2d744b 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c
index af45c79bd..8ba0989b4 100644
--- a/Utilities/cmcurl/lib/wildcard.c
+++ b/Utilities/cmcurl/lib/wildcard.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,9 +30,15 @@
#include "curl_memory.h"
#include "memdebug.h"
+static void fileinfo_dtor(void *user, void *element)
+{
+ (void)user;
+ Curl_fileinfo_cleanup(element);
+}
+
CURLcode Curl_wildcard_init(struct WildcardData *wc)
{
- Curl_llist_init(&wc->filelist, Curl_fileinfo_dtor);
+ Curl_llist_init(&wc->filelist, fileinfo_dtor);
wc->state = CURLWC_INIT;
return CURLE_OK;
@@ -43,12 +49,12 @@ void Curl_wildcard_dtor(struct WildcardData *wc)
if(!wc)
return;
- if(wc->tmp_dtor) {
- wc->tmp_dtor(wc->tmp);
- wc->tmp_dtor = ZERO_NULL;
- wc->tmp = NULL;
+ if(wc->dtor) {
+ wc->dtor(wc->protdata);
+ wc->dtor = ZERO_NULL;
+ wc->protdata = NULL;
}
- DEBUGASSERT(wc->tmp == NULL);
+ DEBUGASSERT(wc->protdata == NULL);
Curl_llist_destroy(&wc->filelist, NULL);
diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h
index 8a5e4b769..b7826123a 100644
--- a/Utilities/cmcurl/lib/wildcard.h
+++ b/Utilities/cmcurl/lib/wildcard.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@ typedef enum {
will end */
} curl_wildcard_states;
-typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
+typedef void (*curl_wildcard_dtor)(void *ptr);
/* struct keeping information about wildcard download process */
struct WildcardData {
@@ -48,8 +48,8 @@ struct WildcardData {
char *path; /* path to the directory, where we trying wildcard-match */
char *pattern; /* wildcard pattern */
struct curl_llist filelist; /* llist with struct Curl_fileinfo */
- void *tmp; /* pointer to protocol specific temporary data */
- curl_wildcard_tmp_dtor tmp_dtor;
+ void *protdata; /* pointer to protocol specific temporary data */
+ curl_wildcard_dtor dtor;
void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
};
diff --git a/Utilities/cmlibuv/include/uv-errno.h b/Utilities/cmlibuv/include/uv-errno.h
index 8a4153314..aa4d4509f 100644
--- a/Utilities/cmlibuv/include/uv-errno.h
+++ b/Utilities/cmlibuv/include/uv-errno.h
@@ -23,6 +23,11 @@
#define UV_ERRNO_H_
#include <errno.h>
+#if EDOM > 0
+# define UV__ERR(x) (-(x))
+#else
+# define UV__ERR(x) (x)
+#endif
#define UV__EOF (-4095)
#define UV__UNKNOWN (-4094)
@@ -46,355 +51,355 @@
* a fairly common practice for Windows programmers to redefine errno codes.
*/
#if defined(E2BIG) && !defined(_WIN32)
-# define UV__E2BIG (-E2BIG)
+# define UV__E2BIG UV__ERR(E2BIG)
#else
# define UV__E2BIG (-4093)
#endif
#if defined(EACCES) && !defined(_WIN32)
-# define UV__EACCES (-EACCES)
+# define UV__EACCES UV__ERR(EACCES)
#else
# define UV__EACCES (-4092)
#endif
#if defined(EADDRINUSE) && !defined(_WIN32)
-# define UV__EADDRINUSE (-EADDRINUSE)
+# define UV__EADDRINUSE UV__ERR(EADDRINUSE)
#else
# define UV__EADDRINUSE (-4091)
#endif
#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
-# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL)
+# define UV__EADDRNOTAVAIL UV__ERR(EADDRNOTAVAIL)
#else
# define UV__EADDRNOTAVAIL (-4090)
#endif
#if defined(EAFNOSUPPORT) && !defined(_WIN32)
-# define UV__EAFNOSUPPORT (-EAFNOSUPPORT)
+# define UV__EAFNOSUPPORT UV__ERR(EAFNOSUPPORT)
#else
# define UV__EAFNOSUPPORT (-4089)
#endif
#if defined(EAGAIN) && !defined(_WIN32)
-# define UV__EAGAIN (-EAGAIN)
+# define UV__EAGAIN UV__ERR(EAGAIN)
#else
# define UV__EAGAIN (-4088)
#endif
#if defined(EALREADY) && !defined(_WIN32)
-# define UV__EALREADY (-EALREADY)
+# define UV__EALREADY UV__ERR(EALREADY)
#else
# define UV__EALREADY (-4084)
#endif
#if defined(EBADF) && !defined(_WIN32)
-# define UV__EBADF (-EBADF)
+# define UV__EBADF UV__ERR(EBADF)
#else
# define UV__EBADF (-4083)
#endif
#if defined(EBUSY) && !defined(_WIN32)
-# define UV__EBUSY (-EBUSY)
+# define UV__EBUSY UV__ERR(EBUSY)
#else
# define UV__EBUSY (-4082)
#endif
#if defined(ECANCELED) && !defined(_WIN32)
-# define UV__ECANCELED (-ECANCELED)
+# define UV__ECANCELED UV__ERR(ECANCELED)
#else
# define UV__ECANCELED (-4081)
#endif
#if defined(ECHARSET) && !defined(_WIN32)
-# define UV__ECHARSET (-ECHARSET)
+# define UV__ECHARSET UV__ERR(ECHARSET)
#else
# define UV__ECHARSET (-4080)
#endif
#if defined(ECONNABORTED) && !defined(_WIN32)
-# define UV__ECONNABORTED (-ECONNABORTED)
+# define UV__ECONNABORTED UV__ERR(ECONNABORTED)
#else
# define UV__ECONNABORTED (-4079)
#endif
#if defined(ECONNREFUSED) && !defined(_WIN32)
-# define UV__ECONNREFUSED (-ECONNREFUSED)
+# define UV__ECONNREFUSED UV__ERR(ECONNREFUSED)
#else
# define UV__ECONNREFUSED (-4078)
#endif
#if defined(ECONNRESET) && !defined(_WIN32)
-# define UV__ECONNRESET (-ECONNRESET)
+# define UV__ECONNRESET UV__ERR(ECONNRESET)
#else
# define UV__ECONNRESET (-4077)
#endif
#if defined(EDESTADDRREQ) && !defined(_WIN32)
-# define UV__EDESTADDRREQ (-EDESTADDRREQ)
+# define UV__EDESTADDRREQ UV__ERR(EDESTADDRREQ)
#else
# define UV__EDESTADDRREQ (-4076)
#endif
#if defined(EEXIST) && !defined(_WIN32)
-# define UV__EEXIST (-EEXIST)
+# define UV__EEXIST UV__ERR(EEXIST)
#else
# define UV__EEXIST (-4075)
#endif
#if defined(EFAULT) && !defined(_WIN32)
-# define UV__EFAULT (-EFAULT)
+# define UV__EFAULT UV__ERR(EFAULT)
#else
# define UV__EFAULT (-4074)
#endif
#if defined(EHOSTUNREACH) && !defined(_WIN32)
-# define UV__EHOSTUNREACH (-EHOSTUNREACH)
+# define UV__EHOSTUNREACH UV__ERR(EHOSTUNREACH)
#else
# define UV__EHOSTUNREACH (-4073)
#endif
#if defined(EINTR) && !defined(_WIN32)
-# define UV__EINTR (-EINTR)
+# define UV__EINTR UV__ERR(EINTR)
#else
# define UV__EINTR (-4072)
#endif
#if defined(EINVAL) && !defined(_WIN32)
-# define UV__EINVAL (-EINVAL)
+# define UV__EINVAL UV__ERR(EINVAL)
#else
# define UV__EINVAL (-4071)
#endif
#if defined(EIO) && !defined(_WIN32)
-# define UV__EIO (-EIO)
+# define UV__EIO UV__ERR(EIO)
#else
# define UV__EIO (-4070)
#endif
#if defined(EISCONN) && !defined(_WIN32)
-# define UV__EISCONN (-EISCONN)
+# define UV__EISCONN UV__ERR(EISCONN)
#else
# define UV__EISCONN (-4069)
#endif
#if defined(EISDIR) && !defined(_WIN32)
-# define UV__EISDIR (-EISDIR)
+# define UV__EISDIR UV__ERR(EISDIR)
#else
# define UV__EISDIR (-4068)
#endif
#if defined(ELOOP) && !defined(_WIN32)
-# define UV__ELOOP (-ELOOP)
+# define UV__ELOOP UV__ERR(ELOOP)
#else
# define UV__ELOOP (-4067)
#endif
#if defined(EMFILE) && !defined(_WIN32)
-# define UV__EMFILE (-EMFILE)
+# define UV__EMFILE UV__ERR(EMFILE)
#else
# define UV__EMFILE (-4066)
#endif
#if defined(EMSGSIZE) && !defined(_WIN32)
-# define UV__EMSGSIZE (-EMSGSIZE)
+# define UV__EMSGSIZE UV__ERR(EMSGSIZE)
#else
# define UV__EMSGSIZE (-4065)
#endif
#if defined(ENAMETOOLONG) && !defined(_WIN32)
-# define UV__ENAMETOOLONG (-ENAMETOOLONG)
+# define UV__ENAMETOOLONG UV__ERR(ENAMETOOLONG)
#else
# define UV__ENAMETOOLONG (-4064)
#endif
#if defined(ENETDOWN) && !defined(_WIN32)
-# define UV__ENETDOWN (-ENETDOWN)
+# define UV__ENETDOWN UV__ERR(ENETDOWN)
#else
# define UV__ENETDOWN (-4063)
#endif
#if defined(ENETUNREACH) && !defined(_WIN32)
-# define UV__ENETUNREACH (-ENETUNREACH)
+# define UV__ENETUNREACH UV__ERR(ENETUNREACH)
#else
# define UV__ENETUNREACH (-4062)
#endif
#if defined(ENFILE) && !defined(_WIN32)
-# define UV__ENFILE (-ENFILE)
+# define UV__ENFILE UV__ERR(ENFILE)
#else
# define UV__ENFILE (-4061)
#endif
#if defined(ENOBUFS) && !defined(_WIN32)
-# define UV__ENOBUFS (-ENOBUFS)
+# define UV__ENOBUFS UV__ERR(ENOBUFS)
#else
# define UV__ENOBUFS (-4060)
#endif
#if defined(ENODEV) && !defined(_WIN32)
-# define UV__ENODEV (-ENODEV)
+# define UV__ENODEV UV__ERR(ENODEV)
#else
# define UV__ENODEV (-4059)
#endif
#if defined(ENOENT) && !defined(_WIN32)
-# define UV__ENOENT (-ENOENT)
+# define UV__ENOENT UV__ERR(ENOENT)
#else
# define UV__ENOENT (-4058)
#endif
#if defined(ENOMEM) && !defined(_WIN32)
-# define UV__ENOMEM (-ENOMEM)
+# define UV__ENOMEM UV__ERR(ENOMEM)
#else
# define UV__ENOMEM (-4057)
#endif
#if defined(ENONET) && !defined(_WIN32)
-# define UV__ENONET (-ENONET)
+# define UV__ENONET UV__ERR(ENONET)
#else
# define UV__ENONET (-4056)
#endif
#if defined(ENOSPC) && !defined(_WIN32)
-# define UV__ENOSPC (-ENOSPC)
+# define UV__ENOSPC UV__ERR(ENOSPC)
#else
# define UV__ENOSPC (-4055)
#endif
#if defined(ENOSYS) && !defined(_WIN32)
-# define UV__ENOSYS (-ENOSYS)
+# define UV__ENOSYS UV__ERR(ENOSYS)
#else
# define UV__ENOSYS (-4054)
#endif
#if defined(ENOTCONN) && !defined(_WIN32)
-# define UV__ENOTCONN (-ENOTCONN)
+# define UV__ENOTCONN UV__ERR(ENOTCONN)
#else
# define UV__ENOTCONN (-4053)
#endif
#if defined(ENOTDIR) && !defined(_WIN32)
-# define UV__ENOTDIR (-ENOTDIR)
+# define UV__ENOTDIR UV__ERR(ENOTDIR)
#else
# define UV__ENOTDIR (-4052)
#endif
#if defined(ENOTEMPTY) && !defined(_WIN32)
-# define UV__ENOTEMPTY (-ENOTEMPTY)
+# define UV__ENOTEMPTY UV__ERR(ENOTEMPTY)
#else
# define UV__ENOTEMPTY (-4051)
#endif
#if defined(ENOTSOCK) && !defined(_WIN32)
-# define UV__ENOTSOCK (-ENOTSOCK)
+# define UV__ENOTSOCK UV__ERR(ENOTSOCK)
#else
# define UV__ENOTSOCK (-4050)
#endif
#if defined(ENOTSUP) && !defined(_WIN32)
-# define UV__ENOTSUP (-ENOTSUP)
+# define UV__ENOTSUP UV__ERR(ENOTSUP)
#else
# define UV__ENOTSUP (-4049)
#endif
#if defined(EPERM) && !defined(_WIN32)
-# define UV__EPERM (-EPERM)
+# define UV__EPERM UV__ERR(EPERM)
#else
# define UV__EPERM (-4048)
#endif
#if defined(EPIPE) && !defined(_WIN32)
-# define UV__EPIPE (-EPIPE)
+# define UV__EPIPE UV__ERR(EPIPE)
#else
# define UV__EPIPE (-4047)
#endif
#if defined(EPROTO) && !defined(_WIN32)
-# define UV__EPROTO (-EPROTO)
+# define UV__EPROTO UV__ERR(EPROTO)
#else
-# define UV__EPROTO (-4046)
+# define UV__EPROTO UV__ERR(4046)
#endif
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
-# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT)
+# define UV__EPROTONOSUPPORT UV__ERR(EPROTONOSUPPORT)
#else
# define UV__EPROTONOSUPPORT (-4045)
#endif
#if defined(EPROTOTYPE) && !defined(_WIN32)
-# define UV__EPROTOTYPE (-EPROTOTYPE)
+# define UV__EPROTOTYPE UV__ERR(EPROTOTYPE)
#else
# define UV__EPROTOTYPE (-4044)
#endif
#if defined(EROFS) && !defined(_WIN32)
-# define UV__EROFS (-EROFS)
+# define UV__EROFS UV__ERR(EROFS)
#else
# define UV__EROFS (-4043)
#endif
#if defined(ESHUTDOWN) && !defined(_WIN32)
-# define UV__ESHUTDOWN (-ESHUTDOWN)
+# define UV__ESHUTDOWN UV__ERR(ESHUTDOWN)
#else
# define UV__ESHUTDOWN (-4042)
#endif
#if defined(ESPIPE) && !defined(_WIN32)
-# define UV__ESPIPE (-ESPIPE)
+# define UV__ESPIPE UV__ERR(ESPIPE)
#else
# define UV__ESPIPE (-4041)
#endif
#if defined(ESRCH) && !defined(_WIN32)
-# define UV__ESRCH (-ESRCH)
+# define UV__ESRCH UV__ERR(ESRCH)
#else
# define UV__ESRCH (-4040)
#endif
#if defined(ETIMEDOUT) && !defined(_WIN32)
-# define UV__ETIMEDOUT (-ETIMEDOUT)
+# define UV__ETIMEDOUT UV__ERR(ETIMEDOUT)
#else
# define UV__ETIMEDOUT (-4039)
#endif
#if defined(ETXTBSY) && !defined(_WIN32)
-# define UV__ETXTBSY (-ETXTBSY)
+# define UV__ETXTBSY UV__ERR(ETXTBSY)
#else
# define UV__ETXTBSY (-4038)
#endif
#if defined(EXDEV) && !defined(_WIN32)
-# define UV__EXDEV (-EXDEV)
+# define UV__EXDEV UV__ERR(EXDEV)
#else
# define UV__EXDEV (-4037)
#endif
#if defined(EFBIG) && !defined(_WIN32)
-# define UV__EFBIG (-EFBIG)
+# define UV__EFBIG UV__ERR(EFBIG)
#else
# define UV__EFBIG (-4036)
#endif
#if defined(ENOPROTOOPT) && !defined(_WIN32)
-# define UV__ENOPROTOOPT (-ENOPROTOOPT)
+# define UV__ENOPROTOOPT UV__ERR(ENOPROTOOPT)
#else
# define UV__ENOPROTOOPT (-4035)
#endif
#if defined(ERANGE) && !defined(_WIN32)
-# define UV__ERANGE (-ERANGE)
+# define UV__ERANGE UV__ERR(ERANGE)
#else
# define UV__ERANGE (-4034)
#endif
#if defined(ENXIO) && !defined(_WIN32)
-# define UV__ENXIO (-ENXIO)
+# define UV__ENXIO UV__ERR(ENXIO)
#else
# define UV__ENXIO (-4033)
#endif
#if defined(EMLINK) && !defined(_WIN32)
-# define UV__EMLINK (-EMLINK)
+# define UV__EMLINK UV__ERR(EMLINK)
#else
# define UV__EMLINK (-4032)
#endif
@@ -404,7 +409,7 @@
* icky to hard-code it.
*/
#if defined(EHOSTDOWN) && !defined(_WIN32)
-# define UV__EHOSTDOWN (-EHOSTDOWN)
+# define UV__EHOSTDOWN UV__ERR(EHOSTDOWN)
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
@@ -417,15 +422,16 @@
#endif
#if defined(EREMOTEIO) && !defined(_WIN32)
-# define UV__EREMOTEIO (-EREMOTEIO)
+# define UV__EREMOTEIO UV__ERR(EREMOTEIO)
#else
# define UV__EREMOTEIO (-4030)
#endif
#if defined(ENOTTY) && !defined(_WIN32)
-# define UV__ENOTTY (-ENOTTY)
+# define UV__ENOTTY UV__ERR(ENOTTY)
#else
# define UV__ENOTTY (-4029)
#endif
+
#endif /* UV_ERRNO_H_ */
diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv-os390.h
index 39e7384db..0267d74cb 100644
--- a/Utilities/cmlibuv/include/uv-os390.h
+++ b/Utilities/cmlibuv/include/uv-os390.h
@@ -22,7 +22,7 @@
#ifndef UV_MVS_H
#define UV_MVS_H
-#define UV_PLATFORM_SEM_T int
+#define UV_PLATFORM_SEM_T long
#define UV_PLATFORM_LOOP_FIELDS \
void* ep; \
diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h
index d8d031f4d..455674d1a 100644
--- a/Utilities/cmlibuv/include/uv-unix.h
+++ b/Utilities/cmlibuv/include/uv-unix.h
@@ -50,7 +50,7 @@
# include "uv-linux.h"
#elif defined (__MVS__)
# include "uv-os390.h"
-#elif defined(_PASE)
+#elif defined(__PASE__)
# include "uv-posix.h"
#elif defined(_AIX)
# include "uv-aix.h"
diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h
index 1dc63e57c..06c6711c6 100644
--- a/Utilities/cmlibuv/include/uv-version.h
+++ b/Utilities/cmlibuv/include/uv-version.h
@@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 19
-#define UV_VERSION_PATCH 1
+#define UV_VERSION_MINOR 20
+#define UV_VERSION_PATCH 3
#define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev"
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index 328ce9ebb..74fa00dfc 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -382,8 +382,7 @@ UV_EXTERN const char* uv_err_name(int err);
/* read-only */ \
uv_req_type type; \
/* private */ \
- void* active_queue[2]; \
- void* reserved[4]; \
+ void* reserved[6]; \
UV_REQ_PRIVATE_FIELDS \
/* Abstract base class of all requests. */
@@ -925,6 +924,19 @@ typedef struct uv_process_options_s {
*/
uv_uid_t uid;
uv_gid_t gid;
+ /*
+ Libuv can set the child process' CPU affinity mask. This happens when
+ `cpumask` is non-NULL. It must point to an array of char values
+ of length `cpumask_size`, whose value must be at least that returned by
+ uv_cpumask_size(). Each byte in the mask can be either zero (false)
+ or non-zero (true) to indicate whether the corresponding processor at
+ that index is included.
+
+ If enabled on an unsupported platform, uv_spawn() will fail with
+ UV_ENOTSUP.
+ */
+ char* cpumask;
+ size_t cpumask_size;
} uv_process_options_t;
/*
@@ -1094,6 +1106,7 @@ UV_EXTERN uv_pid_t uv_os_getppid(void);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
+UV_EXTERN int uv_cpumask_size(void);
UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
int* count);
@@ -1195,6 +1208,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop,
*/
#define UV_FS_COPYFILE_EXCL 0x0001
+/*
+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
+ * If copy-on-write is not supported, a fallback copy mechanism is used.
+ */
+#define UV_FS_COPYFILE_FICLONE 0x0002
+
+/*
+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
+ * If copy-on-write is not supported, an error is returned.
+ */
+#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004
+
UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
@@ -1535,7 +1560,10 @@ struct uv_loop_s {
/* Loop reference counting. */
unsigned int active_handles;
void* handle_queue[2];
- void* active_reqs[2];
+ union {
+ void* unused[2];
+ unsigned int count;
+ } active_reqs;
/* Internal flag to signal loop stop. */
unsigned int stop_flag;
UV_LOOP_PRIVATE_FIELDS
@@ -1563,6 +1591,7 @@ UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
#undef UV_SIGNAL_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS
+#undef UV__ERR
#ifdef __cplusplus
}
diff --git a/Utilities/cmlibuv/src/unix/aix-common.c b/Utilities/cmlibuv/src/unix/aix-common.c
index c2217fb6b..9c11c5dac 100644
--- a/Utilities/cmlibuv/src/unix/aix-common.c
+++ b/Utilities/cmlibuv/src/unix/aix-common.c
@@ -83,12 +83,12 @@ int uv_exepath(char* buffer, size_t* size) {
struct procsinfo pi;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
pi.pi_pid = getpid();
res = getargs(&pi, sizeof(pi), args, sizeof(args));
if (res < 0)
- return -EINVAL;
+ return UV_EINVAL;
/*
* Possibilities for args:
@@ -101,7 +101,7 @@ int uv_exepath(char* buffer, size_t* size) {
/* Case i) and ii) absolute or relative paths */
if (strchr(args, '/') != NULL) {
if (realpath(args, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
@@ -121,11 +121,11 @@ int uv_exepath(char* buffer, size_t* size) {
char *path = getenv("PATH");
if (path == NULL)
- return -EINVAL;
+ return UV_EINVAL;
clonedpath = uv__strdup(path);
if (clonedpath == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
token = strtok(clonedpath, ":");
while (token != NULL) {
@@ -151,7 +151,7 @@ int uv_exepath(char* buffer, size_t* size) {
uv__free(clonedpath);
/* Out of tokens (path entries), and no match found */
- return -EINVAL;
+ return UV_EINVAL;
}
}
@@ -177,19 +177,19 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*count = 0;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
- return -errno;
+ return UV__ERR(errno);
}
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
ifc.ifc_len = size;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
@@ -208,7 +208,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -221,7 +221,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
@@ -240,7 +240,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -260,7 +260,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (inet6)
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index fd413090f..92de81483 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -119,7 +119,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
pc.fd = fd;
if (pollset_ctl(loop->backend_fd, &pc, 1))
- return -errno;
+ return UV__ERR(errno);
pc.cmd = PS_DELETE;
if (pollset_ctl(loop->backend_fd, &pc, 1))
@@ -409,22 +409,22 @@ static int uv__is_ahafs_mounted(void){
p = uv__malloc(siz);
if (p == NULL)
- return -errno;
+ return UV__ERR(errno);
/* Retrieve all mounted filesystems */
rv = mntctl(MCTL_QUERY, siz, (char*)p);
if (rv < 0)
- return -errno;
+ return UV__ERR(errno);
if (rv == 0) {
/* buffer was not large enough, reallocate to correct size */
siz = *(int*)p;
uv__free(p);
p = uv__malloc(siz);
if (p == NULL)
- return -errno;
+ return UV__ERR(errno);
rv = mntctl(MCTL_QUERY, siz, (char*)p);
if (rv < 0)
- return -errno;
+ return UV__ERR(errno);
}
/* Look for dev in filesystems mount info */
@@ -495,7 +495,7 @@ static int uv__make_subdirs_p(const char *filename) {
rc = uv__makedir_p(cmd);
if (rc == -1 && errno != EEXIST){
- return -errno;
+ return UV__ERR(errno);
}
return rc;
@@ -522,7 +522,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
sprintf(mon_file, "/aha/fs/modFile.monFactory");
if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX)
- return -ENAMETOOLONG;
+ return UV_ENAMETOOLONG;
/* Make the necessary subdirectories for the monitor file */
rc = uv__make_subdirs_p(filename);
@@ -537,7 +537,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
/* Open the monitor file, creating it if necessary */
*fd = open(mon_file, O_CREAT|O_RDWR);
if (*fd < 0)
- return -errno;
+ return UV__ERR(errno);
/* Write out the monitoring specifications.
* In this case, we are monitoring for a state change event type
@@ -558,7 +558,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
if (rc < 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -716,7 +716,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -771,7 +771,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -796,7 +796,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -861,7 +861,7 @@ int uv_set_process_title(const char* title) {
*/
new_title = uv__strdup(title);
if (new_title == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -888,9 +888,9 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
len = strlen(process_argv[0]);
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
else if (size <= len)
- return -ENOBUFS;
+ return UV_ENOBUFS;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -919,10 +919,10 @@ int uv_resident_set_memory(size_t* rss) {
fd = open(pp, O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
/* FIXME(bnoordhuis) Handle EINTR. */
- err = -EINVAL;
+ err = UV_EINVAL;
if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
*rss = (size_t)psinfo.pr_rssize * 1024;
err = 0;
@@ -953,7 +953,7 @@ int uv_uptime(double* uptime) {
endutent();
if (boot_time == 0)
- return -ENOSYS;
+ return UV_ENOSYS;
*uptime = time(NULL) - boot_time;
return 0;
@@ -969,30 +969,30 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
if (result == -1) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
if (result == -1) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t));
if (!ps_cpus) {
- return -ENOMEM;
+ return UV_ENOMEM;
}
strcpy(cpu_id.name, FIRST_CPU);
result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
if (result == -1) {
uv__free(ps_cpus);
- return -ENOSYS;
+ return UV_ENOSYS;
}
*cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
uv__free(ps_cpus);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = ncpus;
diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c
index 45c088ea1..0b450ae0d 100644
--- a/Utilities/cmlibuv/src/unix/async.c
+++ b/Utilities/cmlibuv/src/unix/async.c
@@ -166,7 +166,7 @@ static int uv__async_start(uv_loop_t* loop) {
pipefd[0] = err;
pipefd[1] = -1;
}
- else if (err == -ENOSYS) {
+ else if (err == UV_ENOSYS) {
err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
#if defined(__linux__)
/* Save a file descriptor by opening one of the pipe descriptors as
@@ -240,7 +240,7 @@ static int uv__async_eventfd(void) {
return fd;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_eventfd2 = 1;
@@ -257,7 +257,7 @@ skip_eventfd2:
}
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_eventfd = 1;
@@ -265,5 +265,5 @@ skip_eventfd:
#endif
- return -ENOSYS;
+ return UV_ENOSYS;
}
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
index ea3166c5e..0d0215448 100644
--- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -70,7 +70,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
int i;
if (getifaddrs(&addrs) != 0)
- return -errno;
+ return UV__ERR(errno);
*count = 0;
@@ -85,7 +85,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (*addresses == NULL) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index c7e431e52..a357ef32d 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -40,6 +40,7 @@
#include <sys/uio.h> /* writev */
#include <sys/resource.h> /* getrusage */
#include <pwd.h>
+#include <sched.h>
#ifdef __sun
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
@@ -63,6 +64,8 @@
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
+# include <sys/param.h>
+# include <sys/cpuset.h>
# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
@@ -191,14 +194,14 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
socklen_t len;
if (handle == NULL || value == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE)
fd = uv__stream_fd((uv_stream_t*) handle);
else if (handle->type == UV_UDP)
fd = ((uv_udp_t *) handle)->io_watcher.fd;
else
- return -ENOTSUP;
+ return UV_ENOTSUP;
len = sizeof(*value);
@@ -208,7 +211,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len);
if (r < 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -418,12 +421,12 @@ int uv__socket(int domain, int type, int protocol) {
return sockfd;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
#endif
sockfd = socket(domain, type, protocol);
if (sockfd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__nonblock(sockfd, 1);
if (err == 0)
@@ -487,7 +490,7 @@ int uv__accept(int sockfd) {
continue;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_accept4 = 1;
skip:
@@ -497,7 +500,7 @@ skip:
if (peerfd == -1) {
if (errno == EINTR)
continue;
- return -errno;
+ return UV__ERR(errno);
}
err = uv__cloexec(peerfd, 1);
@@ -523,8 +526,8 @@ int uv__close_nocheckstdio(int fd) {
saved_errno = errno;
rc = close(fd);
if (rc == -1) {
- rc = -errno;
- if (rc == -EINTR || rc == -EINPROGRESS)
+ rc = UV__ERR(errno);
+ if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
rc = 0; /* The close is in progress, not an error. */
errno = saved_errno;
}
@@ -536,7 +539,7 @@ int uv__close_nocheckstdio(int fd) {
int uv__close(int fd) {
assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
#if defined(__MVS__)
- epoll_file_close(fd);
+ SAVE_ERRNO(epoll_file_close(fd));
#endif
return uv__close_nocheckstdio(fd);
}
@@ -550,7 +553,7 @@ int uv__nonblock_ioctl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -565,7 +568,7 @@ int uv__cloexec_ioctl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -581,7 +584,7 @@ int uv__nonblock_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
/* Bail out now if already set/clear. */
if (!!(r & O_NONBLOCK) == !!set)
@@ -597,7 +600,7 @@ int uv__nonblock_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -612,7 +615,7 @@ int uv__cloexec_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
/* Bail out now if already set/clear. */
if (!!(r & FD_CLOEXEC) == !!set)
@@ -628,7 +631,7 @@ int uv__cloexec_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -643,7 +646,7 @@ int uv__dup(int fd) {
fd = dup(fd);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
@@ -667,10 +670,10 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
if (rc != -1)
return rc;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
rc = recvmsg(fd, msg, flags);
if (rc == -1)
- return -errno;
+ return UV__ERR(errno);
no_msg_cmsg_cloexec = 1;
} else {
rc = recvmsg(fd, msg, flags);
@@ -679,7 +682,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
rc = recvmsg(fd, msg, flags);
#endif
if (rc == -1)
- return -errno;
+ return UV__ERR(errno);
if (msg->msg_controllen == 0)
return rc;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
@@ -695,10 +698,10 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
int uv_cwd(char* buffer, size_t* size) {
if (buffer == NULL || size == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (getcwd(buffer, *size) == NULL)
- return -errno;
+ return UV__ERR(errno);
*size = strlen(buffer);
if (*size > 1 && buffer[*size - 1] == '/') {
@@ -712,7 +715,7 @@ int uv_cwd(char* buffer, size_t* size) {
int uv_chdir(const char* dir) {
if (chdir(dir))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -749,11 +752,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (uv__is_closing(handle) || fd_out == -1)
- return -EBADF;
+ return UV_EBADF;
*fd = fd_out;
return 0;
@@ -931,7 +934,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage))
- return -errno;
+ return UV__ERR(errno);
rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
@@ -973,7 +976,7 @@ int uv__open_cloexec(const char* path, int flags) {
return fd;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
/* O_CLOEXEC not supported. */
no_cloexec = 1;
@@ -982,7 +985,7 @@ int uv__open_cloexec(const char* path, int flags) {
fd = open(path, flags);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
@@ -999,14 +1002,14 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
r = dup3(oldfd, newfd, O_CLOEXEC);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
return r;
#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
if (r != -1)
return r;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
/* Fall through. */
#elif defined(__linux__)
static int no_dup3;
@@ -1017,7 +1020,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
if (r != -1)
return r;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
/* Fall through. */
no_dup3 = 1;
}
@@ -1033,7 +1036,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
#endif
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(newfd, 1);
if (err) {
@@ -1048,29 +1051,16 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
- char* buf;
size_t len;
int r;
- if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
-
- /* Check if the HOME environment variable is set first */
- buf = getenv("HOME");
-
- if (buf != NULL) {
- len = strlen(buf);
+ /* Check if the HOME environment variable is set first. The task of
+ performing input validation on buffer and size is taken care of by
+ uv_os_getenv(). */
+ r = uv_os_getenv("HOME", buffer, size);
- if (len >= *size) {
- *size = len + 1;
- return -ENOBUFS;
- }
-
- memcpy(buffer, buf, len + 1);
- *size = len;
-
- return 0;
- }
+ if (r != UV_ENOENT)
+ return r;
/* HOME is not set, so call uv__getpwuid_r() */
r = uv__getpwuid_r(&pwd);
@@ -1084,7 +1074,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
if (len >= *size) {
*size = len + 1;
uv_os_free_passwd(&pwd);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, pwd.homedir, len + 1);
@@ -1100,7 +1090,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
#define CHECK_ENV_VAR(name) \
do { \
@@ -1130,7 +1120,7 @@ return_buffer:
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
/* The returned directory should not have a trailing slash. */
@@ -1162,11 +1152,11 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
if (getpwuid_r == NULL)
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
if (pwd == NULL)
- return -EINVAL;
+ return UV_EINVAL;
initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
@@ -1183,7 +1173,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
buf = uv__malloc(bufsize);
if (buf == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
@@ -1200,7 +1190,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (result == NULL) {
uv__free(buf);
- return -ENOENT;
+ return UV_ENOENT;
}
/* Allocate memory for the username, shell, and home directory */
@@ -1211,7 +1201,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (pwd->username == NULL) {
uv__free(buf);
- return -ENOMEM;
+ return UV_ENOMEM;
}
/* Copy the username */
@@ -1267,18 +1257,18 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
size_t len;
if (name == NULL || buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
var = getenv(name);
if (var == NULL)
- return -ENOENT;
+ return UV_ENOENT;
len = strlen(var);
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, var, len + 1);
@@ -1290,10 +1280,10 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
int uv_os_setenv(const char* name, const char* value) {
if (name == NULL || value == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (setenv(name, value, 1) != 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -1301,10 +1291,10 @@ int uv_os_setenv(const char* name, const char* value) {
int uv_os_unsetenv(const char* name) {
if (name == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (unsetenv(name) != 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -1321,17 +1311,17 @@ int uv_os_gethostname(char* buffer, size_t* size) {
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
if (gethostname(buf, sizeof(buf)) != 0)
- return -errno;
+ return UV__ERR(errno);
buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
len = strlen(buf);
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, buf, len + 1);
@@ -1340,6 +1330,15 @@ int uv_os_gethostname(char* buffer, size_t* size) {
}
+int uv_cpumask_size(void) {
+#if defined(__linux__) || defined(__FreeBSD__)
+ return CPU_SETSIZE;
+#else
+ return UV_ENOTSUP;
+#endif
+}
+
+
uv_os_fd_t uv_get_osfhandle(int fd) {
return fd;
}
diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c
index 5a887dd4c..9fe4093ef 100644
--- a/Utilities/cmlibuv/src/unix/cygwin.c
+++ b/Utilities/cmlibuv/src/unix/cygwin.c
@@ -29,7 +29,7 @@ int uv_uptime(double* uptime) {
struct sysinfo info;
if (sysinfo(&info) < 0)
- return -errno;
+ return UV__ERR(errno);
*uptime = info.uptime;
return 0;
diff --git a/Utilities/cmlibuv/src/unix/darwin-proctitle.c b/Utilities/cmlibuv/src/unix/darwin-proctitle.c
index 114231160..dabde2239 100644
--- a/Utilities/cmlibuv/src/unix/darwin-proctitle.c
+++ b/Utilities/cmlibuv/src/unix/darwin-proctitle.c
@@ -18,6 +18,9 @@
* IN THE SOFTWARE.
*/
+#include "uv.h"
+#include "internal.h"
+
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
@@ -41,14 +44,14 @@ static int uv__pthread_setname_np(const char* name) {
dlsym(RTLD_DEFAULT, "pthread_setname_np");
if (dynamic_pthread_setname_np == NULL)
- return -ENOSYS;
+ return UV_ENOSYS;
strncpy(namebuf, name, sizeof(namebuf) - 1);
namebuf[sizeof(namebuf) - 1] = '\0';
err = dynamic_pthread_setname_np(namebuf);
if (err)
- return -err;
+ return UV__ERR(err);
return 0;
}
@@ -84,7 +87,7 @@ int uv__set_process_title(const char* title) {
CFTypeRef asn;
int err;
- err = -ENOENT;
+ err = UV_ENOENT;
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
@@ -151,7 +154,7 @@ int uv__set_process_title(const char* title) {
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
hi_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
- err = -ENOENT;
+ err = UV_ENOENT;
if (hi_services_bundle == NULL)
goto out;
@@ -182,7 +185,7 @@ int uv__set_process_title(const char* title) {
asn = pLSGetCurrentApplicationASN();
- err = -EINVAL;
+ err = UV_EINVAL;
if (pLSSetApplicationInformationItem(-2, /* Magic value. */
asn,
*display_name_key,
diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c
index df6dd1c61..31ad8a9e4 100644
--- a/Utilities/cmlibuv/src/unix/darwin.c
+++ b/Utilities/cmlibuv/src/unix/darwin.c
@@ -37,7 +37,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
loop->cf_state = NULL;
if (uv__kqueue_init(loop))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -68,18 +68,18 @@ int uv_exepath(char* buffer, size_t* size) {
size_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
exepath_size = sizeof(exepath);
if (_NSGetExecutablePath(exepath, &exepath_size))
- return -EIO;
+ return UV_EIO;
if (realpath(exepath, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
if (abspath_size == 0)
- return -EIO;
+ return UV_EIO;
*size -= 1;
if (*size > abspath_size)
@@ -98,7 +98,7 @@ uint64_t uv_get_free_memory(void) {
if (host_statistics(mach_host_self(), HOST_VM_INFO,
(host_info_t)&info, &count) != KERN_SUCCESS) {
- return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
+ return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
@@ -111,7 +111,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -158,7 +158,7 @@ int uv_uptime(double* uptime) {
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
*uptime = now - info.tv_sec;
@@ -181,23 +181,23 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
sysctlbyname("hw.model", &model, &size, NULL, 0)) {
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(cpuspeed);
if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
(processor_info_array_t*)&info,
&msg_type) != KERN_SUCCESS) {
- return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
+ return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = numcpus;
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index f2b3f247a..70ccb1304 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -72,11 +72,11 @@ int uv_exepath(char* buffer, size_t* size) {
ssize_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath));
if (abspath_size < 0)
- return -errno;
+ return UV__ERR(errno);
assert(abspath_size > 0);
*size -= 1;
@@ -96,7 +96,7 @@ int uv_exepath(char* buffer, size_t* size) {
size_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
@@ -105,7 +105,7 @@ int uv_exepath(char* buffer, size_t* size) {
abspath_size = sizeof abspath;
if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
assert(abspath_size > 0);
abspath_size -= 1;
@@ -126,7 +126,7 @@ uint64_t uv_get_free_memory(void) {
size_t size = sizeof(freecount);
if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) freecount * sysconf(_SC_PAGESIZE);
@@ -140,7 +140,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -176,7 +176,7 @@ int uv_set_process_title(const char* title) {
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
@@ -204,7 +204,7 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -214,7 +214,7 @@ int uv_get_process_title(char* buffer, size_t size) {
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
@@ -243,7 +243,7 @@ int uv_resident_set_memory(size_t* rss) {
kinfo_size = sizeof(kinfo);
if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
page_size = getpagesize();
@@ -262,7 +262,7 @@ int uv_uptime(double* uptime) {
struct timespec sp;
r = clock_gettime(CLOCK_MONOTONIC, &sp);
if (r)
- return -errno;
+ return UV__ERR(errno);
*uptime = sp.tv_sec;
return 0;
@@ -309,15 +309,15 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctlbyname(model_key, &model, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
- return -ENOMEM;
+ return UV_ENOMEM;
*count = numcpus;
@@ -327,7 +327,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(maxcpus);
if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
size = maxcpus * CPUSTATES * sizeof(long);
@@ -335,13 +335,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
cp_times = uv__malloc(size);
if (cp_times == NULL) {
uv__free(*cpu_infos);
- return -ENOMEM;
+ return UV_ENOMEM;
}
if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) {
uv__free(cp_times);
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
for (i = 0; i < numcpus; i++) {
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 0a4c183eb..4545168f2 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -62,21 +62,23 @@
#if defined(__APPLE__)
# include <copyfile.h>
+#elif defined(__linux__) && !defined(FICLONE)
+# include <sys/ioctl.h>
+# define FICLONE _IOW(0x94, 9, int)
#endif
#define INIT(subtype) \
do { \
if (req == NULL) \
- return -EINVAL; \
- req->type = UV_FS; \
- if (cb != NULL) \
- uv__req_init(loop, req, UV_FS); \
+ return UV_EINVAL; \
+ UV_REQ_INIT(req, UV_FS); \
req->fs_type = UV_FS_ ## subtype; \
req->result = 0; \
req->ptr = NULL; \
req->loop = loop; \
req->path = NULL; \
req->new_path = NULL; \
+ req->bufs = NULL; \
req->cb = cb; \
} \
while (0)
@@ -88,10 +90,8 @@
req->path = path; \
} else { \
req->path = uv__strdup(path); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
} \
} \
while (0)
@@ -107,10 +107,8 @@
path_len = strlen(path) + 1; \
new_path_len = strlen(new_path) + 1; \
req->path = uv__malloc(path_len + new_path_len); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
req->new_path = req->path + path_len; \
memcpy((void*) req->path, path, path_len); \
memcpy((void*) req->new_path, new_path, new_path_len); \
@@ -121,6 +119,7 @@
#define POST \
do { \
if (cb != NULL) { \
+ uv__req_register(loop, req); \
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
return 0; \
} \
@@ -804,6 +803,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
if (req->flags & UV_FS_COPYFILE_EXCL)
flags |= COPYFILE_EXCL;
+#ifdef COPYFILE_CLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE)
+ flags |= COPYFILE_CLONE;
+#endif
+
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+#ifdef COPYFILE_CLONE_FORCE
+ flags |= COPYFILE_CLONE_FORCE;
+#else
+ return UV_ENOSYS;
+#endif
+ }
+
return copyfile(req->path, req->new_path, NULL, flags);
#else
uv_fs_t fs_req;
@@ -828,7 +840,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
/* Get the source file's mode. */
if (fstat(srcfd, &statsbuf)) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
@@ -852,9 +864,32 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
}
if (fchmod(dstfd, statsbuf.st_mode) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
+ goto out;
+ }
+
+#ifdef FICLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ if (ioctl(dstfd, FICLONE, srcfd) == -1) {
+ /* If an error occurred that the sendfile fallback also won't handle, or
+ this is a force clone then exit. Otherwise, fall through to try using
+ sendfile(). */
+ if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = -errno;
+ goto out;
+ }
+ } else {
+ goto out;
+ }
+ }
+#else
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = UV_ENOSYS;
goto out;
}
+#endif
bytes_to_send = statsbuf.st_size;
in_offset = 0;
@@ -1117,7 +1152,7 @@ static void uv__fs_work(struct uv__work* w) {
} while (r == -1 && errno == EINTR && retry_on_eintr);
if (r == -1)
- req->result = -errno;
+ req->result = UV__ERR(errno);
else
req->result = r;
@@ -1135,9 +1170,9 @@ static void uv__fs_done(struct uv__work* w, int status) {
req = container_of(w, uv_fs_t, work_req);
uv__req_unregister(req->loop, req);
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->result == 0);
- req->result = -ECANCELED;
+ req->result = UV_ECANCELED;
}
req->cb(req);
@@ -1298,11 +1333,8 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(MKDTEMP);
req->path = uv__strdup(tpl);
- if (req->path == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->path == NULL)
+ return UV_ENOMEM;
POST;
}
@@ -1330,7 +1362,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
INIT(READ);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
@@ -1339,11 +1371,8 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@@ -1469,7 +1498,7 @@ int uv_fs_write(uv_loop_t* loop,
INIT(WRITE);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
@@ -1478,11 +1507,8 @@ int uv_fs_write(uv_loop_t* loop,
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@@ -1509,6 +1535,10 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
uv__fs_scandir_cleanup(req);
+ if (req->bufs != req->bufsml)
+ uv__free(req->bufs);
+ req->bufs = NULL;
+
if (req->ptr != &req->statbuf)
uv__free(req->ptr);
req->ptr = NULL;
@@ -1523,8 +1553,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
- return -EINVAL;
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
+ return UV_EINVAL;
+ }
PATH2;
req->flags = flags;
diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c
index 38837406a..47d8024b6 100644
--- a/Utilities/cmlibuv/src/unix/fsevents.c
+++ b/Utilities/cmlibuv/src/unix/fsevents.c
@@ -379,7 +379,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) {
if (!pFSEventStreamStart(ref)) {
pFSEventStreamInvalidate(ref);
pFSEventStreamRelease(ref);
- return -EMFILE;
+ return UV_EMFILE;
}
state->fsevent_stream = ref;
@@ -440,7 +440,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle,
uv__fsevents_destroy_stream(handle->loop);
/* Any failure below will be a memory failure */
- err = -ENOMEM;
+ err = UV_ENOMEM;
/* Create list of all watched paths */
uv_mutex_lock(&state->fsevent_mutex);
@@ -474,7 +474,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle,
/* Create new FSEventStream */
cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL);
if (cf_paths == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto final;
}
err = uv__fsevents_create_stream(handle->loop, cf_paths);
@@ -528,7 +528,7 @@ static int uv__fsevents_global_init(void) {
* but if it ever becomes one, we can turn the dynamic library handles into
* per-event loop properties and have the dynamic linker keep track for us.
*/
- err = -ENOSYS;
+ err = UV_ENOSYS;
core_foundation_handle = dlopen("/System/Library/Frameworks/"
"CoreFoundation.framework/"
"Versions/A/CoreFoundation",
@@ -543,7 +543,7 @@ static int uv__fsevents_global_init(void) {
if (core_services_handle == NULL)
goto out;
- err = -ENOENT;
+ err = UV_ENOENT;
#define V(handle, symbol) \
do { \
*(void **)(&p ## symbol) = dlsym((handle), #symbol); \
@@ -607,7 +607,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
state = uv__calloc(1, sizeof(*state));
if (state == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
err = uv_mutex_init(&loop->cf_mutex);
if (err)
@@ -636,7 +636,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
ctx.perform = uv__cf_loop_cb;
state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx);
if (state->signal_source == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto fail_signal_source_create;
}
@@ -655,7 +655,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
loop->cf_state = state;
/* uv_thread_t is an alias for pthread_t. */
- err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop);
+ err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));
if (attr != NULL)
pthread_attr_destroy(attr);
@@ -787,7 +787,7 @@ int uv__cf_loop_signal(uv_loop_t* loop,
item = uv__malloc(sizeof(*item));
if (item == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
item->handle = handle;
item->type = type;
@@ -817,7 +817,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
/* Get absolute path to file */
handle->realpath = realpath(handle->path, NULL);
if (handle->realpath == NULL)
- return -errno;
+ return UV__ERR(errno);
handle->realpath_len = strlen(handle->realpath);
/* Initialize event queue */
@@ -830,7 +830,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
*/
handle->cf_cb = uv__malloc(sizeof(*handle->cf_cb));
if (handle->cf_cb == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto fail_cf_cb_malloc;
}
@@ -881,7 +881,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) {
uv__cf_loop_state_t* state;
if (handle->cf_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
/* Remove handle from the list */
state = handle->loop->cf_state;
@@ -895,7 +895,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) {
assert(handle != NULL);
err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing);
if (err)
- return -err;
+ return UV__ERR(err);
/* Wait for deinitialization */
uv_sem_wait(&state->fsevent_sem);
diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c
index 018597169..10e8afd75 100644
--- a/Utilities/cmlibuv/src/unix/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c
@@ -86,7 +86,7 @@ int uv__getaddrinfo_translate_error(int sys_err) {
case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE;
#endif
#if defined(EAI_SYSTEM)
- case EAI_SYSTEM: return -errno;
+ case EAI_SYSTEM: return UV__ERR(errno);
#endif
}
assert(!"unknown EAI_* error code");
@@ -125,7 +125,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
req->service = NULL;
req->hostname = NULL;
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
}
@@ -148,7 +148,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
char* buf;
if (req == NULL || (hostname == NULL && service == NULL))
- return -EINVAL;
+ return UV_EINVAL;
hostname_len = hostname ? strlen(hostname) + 1 : 0;
service_len = service ? strlen(service) + 1 : 0;
@@ -156,7 +156,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
buf = uv__malloc(hostname_len + service_len + hints_len);
if (buf == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
uv__req_init(loop, req, UV_GETADDRINFO);
req->loop = loop;
@@ -211,7 +211,7 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
return UV_EINVAL;
if (if_indextoname(ifindex, ifname_buf) == NULL)
- return -errno;
+ return UV__ERR(errno);
len = strnlen(ifname_buf, sizeof(ifname_buf));
diff --git a/Utilities/cmlibuv/src/unix/getnameinfo.c b/Utilities/cmlibuv/src/unix/getnameinfo.c
index b2879d69b..d9e6f79d4 100644
--- a/Utilities/cmlibuv/src/unix/getnameinfo.c
+++ b/Utilities/cmlibuv/src/unix/getnameinfo.c
@@ -61,7 +61,7 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) {
uv__req_unregister(req->loop, req);
host = service = NULL;
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
} else if (req->retcode == 0) {
diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c
index c19e2fc37..02e90fb1f 100644
--- a/Utilities/cmlibuv/src/unix/ibmi.c
+++ b/Utilities/cmlibuv/src/unix/ibmi.c
@@ -92,7 +92,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
- return -ENOMEM;
+ return UV_ENOMEM;
}
cpu_info = *cpu_infos;
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 668e57663..89c6eb13d 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -29,6 +29,7 @@
#include <string.h> /* strrchr */
#include <fcntl.h> /* O_CLOEXEC, may be */
#include <stdio.h>
+#include <errno.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -184,7 +185,7 @@ struct uv__stream_queued_fds_s {
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
- (defined(__linux__) && !defined(__sparc__)) || \
+ defined(__linux__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
#define uv__cloexec uv__cloexec_ioctl
@@ -194,12 +195,24 @@ struct uv__stream_queued_fds_s {
#define uv__nonblock uv__nonblock_fcntl
#endif
+/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
+ * when O_NDELAY is not equal to O_NONBLOCK. Case in point: linux/sparc32
+ * and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit.
+ *
+ * Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it
+ * commutes with uv__nonblock().
+ */
+#if defined(__linux__) && O_NDELAY != O_NONBLOCK
+#undef uv__nonblock
+#define uv__nonblock uv__nonblock_fcntl
+#endif
+
/* core */
int uv__cloexec_ioctl(int fd, int set);
int uv__cloexec_fcntl(int fd, int set);
int uv__nonblock_ioctl(int fd, int set);
int uv__nonblock_fcntl(int fd, int set);
-int uv__close(int fd);
+int uv__close(int fd); /* preserves errno */
int uv__close_nocheckstdio(int fd);
int uv__socket(int domain, int type, int protocol);
int uv__dup(int fd);
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index 5e89bdced..a30fd730f 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -51,7 +51,7 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
int uv__kqueue_init(uv_loop_t* loop) {
loop->backend_fd = kqueue();
if (loop->backend_fd == -1)
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(loop->backend_fd, 1);
@@ -98,7 +98,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
rc = 0;
EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
- rc = -errno;
+ rc = UV__ERR(errno);
EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
if (rc == 0)
@@ -458,12 +458,12 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int fd;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index 4d480ce10..b63c25f3c 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -101,7 +101,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
loop->inotify_watchers = NULL;
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -175,7 +175,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
rc = 0;
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
if (errno != EEXIST)
- rc = -errno;
+ rc = UV__ERR(errno);
if (rc == 0)
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
@@ -485,7 +485,7 @@ int uv_resident_set_memory(size_t* rss) {
while (fd == -1 && errno == EINTR);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
do
n = read(fd, buf, sizeof(buf) - 1);
@@ -493,7 +493,7 @@ int uv_resident_set_memory(size_t* rss) {
uv__close(fd);
if (n == -1)
- return -errno;
+ return UV__ERR(errno);
buf[n] = '\0';
s = strchr(buf, ' ');
@@ -525,7 +525,7 @@ int uv_resident_set_memory(size_t* rss) {
return 0;
err:
- return -EINVAL;
+ return UV_EINVAL;
}
@@ -547,7 +547,7 @@ int uv_uptime(double* uptime) {
}
if (r)
- return -errno;
+ return UV__ERR(errno);
*uptime = now.tv_sec;
return 0;
@@ -559,7 +559,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
char buf[1024];
if (!fgets(buf, sizeof(buf), statfile_fp))
- return -EIO;
+ return UV_EIO;
num = 0;
while (fgets(buf, sizeof(buf), statfile_fp)) {
@@ -569,7 +569,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
}
if (num == 0)
- return -EIO;
+ return UV_EIO;
*numcpus = num;
return 0;
@@ -587,13 +587,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
statfile_fp = uv__open_file("/proc/stat");
if (statfile_fp == NULL)
- return -errno;
+ return UV__ERR(errno);
err = uv__cpu_num(statfile_fp, &numcpus);
if (err < 0)
goto out;
- err = -ENOMEM;
+ err = UV_ENOMEM;
ci = uv__calloc(numcpus, sizeof(*ci));
if (ci == NULL)
goto out;
@@ -667,7 +667,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
defined(__x86_64__)
fp = uv__open_file("/proc/cpuinfo");
if (fp == NULL)
- return -errno;
+ return UV__ERR(errno);
while (fgets(buf, sizeof(buf), fp)) {
if (model_idx < numcpus) {
@@ -676,7 +676,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
- return -ENOMEM;
+ return UV_ENOMEM;
}
ci[model_idx++].model = model;
continue;
@@ -695,7 +695,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
- return -ENOMEM;
+ return UV_ENOMEM;
}
ci[model_idx++].model = model;
continue;
@@ -725,7 +725,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
while (model_idx < numcpus) {
model = uv__strndup(inferred_model, strlen(inferred_model));
if (model == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
ci[model_idx++].model = model;
}
@@ -854,7 +854,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
int uv_interface_addresses(uv_interface_address_t** addresses,
int* count) {
#ifndef HAVE_IFADDRS_H
- return -ENOSYS;
+ return UV_ENOSYS;
#else
struct ifaddrs *addrs, *ent;
uv_interface_address_t* address;
@@ -862,7 +862,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
struct sockaddr_ll *sll;
if (getifaddrs(&addrs))
- return -errno;
+ return UV__ERR(errno);
*count = 0;
*addresses = NULL;
@@ -881,7 +881,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c
index 5934c5d8c..bcad630fa 100644
--- a/Utilities/cmlibuv/src/unix/linux-inotify.c
+++ b/Utilities/cmlibuv/src/unix/linux-inotify.c
@@ -73,11 +73,11 @@ static int new_inotify_fd(void) {
return fd;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
fd = uv__inotify_init();
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err == 0)
@@ -283,7 +283,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int wd;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
err = init_inotify(handle->loop);
if (err)
@@ -300,7 +300,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events);
if (wd == -1)
- return -errno;
+ return UV__ERR(errno);
w = find_watcher(handle->loop, wd);
if (w)
@@ -308,7 +308,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
w = uv__malloc(sizeof(*w) + strlen(path) + 1);
if (w == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
w->wd = wd;
w->path = strcpy((char*)(w + 1), path);
diff --git a/Utilities/cmlibuv/src/unix/loop-watcher.c b/Utilities/cmlibuv/src/unix/loop-watcher.c
index 340bb0dfa..b8c1c2a71 100644
--- a/Utilities/cmlibuv/src/unix/loop-watcher.c
+++ b/Utilities/cmlibuv/src/unix/loop-watcher.c
@@ -31,7 +31,7 @@
\
int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
if (uv__is_active(handle)) return 0; \
- if (cb == NULL) return -EINVAL; \
+ if (cb == NULL) return UV_EINVAL; \
QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \
handle->name##_cb = cb; \
uv__handle_start(handle); \
diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c
index 5b5b0e095..99ead6cbc 100644
--- a/Utilities/cmlibuv/src/unix/loop.c
+++ b/Utilities/cmlibuv/src/unix/loop.c
@@ -38,13 +38,14 @@ int uv_loop_init(uv_loop_t* loop) {
heap_init((struct heap*) &loop->timer_heap);
QUEUE_INIT(&loop->wq);
- QUEUE_INIT(&loop->active_reqs);
QUEUE_INIT(&loop->idle_handles);
QUEUE_INIT(&loop->async_handles);
QUEUE_INIT(&loop->check_handles);
QUEUE_INIT(&loop->prepare_handles);
QUEUE_INIT(&loop->handle_queue);
+ loop->active_handles = 0;
+ loop->active_reqs.count = 0;
loop->nfds = 0;
loop->watchers = NULL;
loop->nwatchers = 0;
diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c
index 742507233..2605c114b 100644
--- a/Utilities/cmlibuv/src/unix/netbsd.c
+++ b/Utilities/cmlibuv/src/unix/netbsd.c
@@ -82,7 +82,7 @@ int uv_exepath(char* buffer, size_t* size) {
int mib[4];
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
@@ -91,7 +91,7 @@ int uv_exepath(char* buffer, size_t* size) {
int_size = ARRAY_SIZE(int_buf);
if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
/* Copy string from the intermediate buffer to outer one with appropriate
* length.
@@ -111,7 +111,7 @@ uint64_t uv_get_free_memory(void) {
int which[] = {CTL_VM, VM_UVMEXP};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
}
@@ -128,7 +128,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -150,7 +150,7 @@ int uv_set_process_title(const char* title) {
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
@@ -167,7 +167,7 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -177,7 +177,7 @@ int uv_get_process_title(char* buffer, size_t size) {
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
@@ -219,7 +219,7 @@ int uv_resident_set_memory(size_t* rss) {
error:
if (kd) kvm_close(kd);
- return -EPERM;
+ return UV_EPERM;
}
@@ -230,7 +230,7 @@ int uv_uptime(double* uptime) {
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
@@ -254,12 +254,12 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) &&
sysctlbyname("hw.model", &model, &size, NULL, 0)) {
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*count = numcpus;
/* Only i386 and amd64 have machdep.tsc_freq */
@@ -270,16 +270,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = numcpus * CPUSTATES * sizeof(*cp_times);
cp_times = uv__malloc(size);
if (cp_times == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
uv__free(cp_times);
uv__free(*cpu_infos);
- return -ENOMEM;
+ return UV_ENOMEM;
}
for (i = 0; i < numcpus; i++) {
diff --git a/Utilities/cmlibuv/src/unix/no-fsevents.c b/Utilities/cmlibuv/src/unix/no-fsevents.c
index 38fb6ab0b..158643af1 100644
--- a/Utilities/cmlibuv/src/unix/no-fsevents.c
+++ b/Utilities/cmlibuv/src/unix/no-fsevents.c
@@ -25,16 +25,16 @@
#include <errno.h>
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
const char* filename, unsigned int flags) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
diff --git a/Utilities/cmlibuv/src/unix/no-proctitle.c b/Utilities/cmlibuv/src/unix/no-proctitle.c
index a5c19fbff..165740ca3 100644
--- a/Utilities/cmlibuv/src/unix/no-proctitle.c
+++ b/Utilities/cmlibuv/src/unix/no-proctitle.c
@@ -35,7 +35,7 @@ int uv_set_process_title(const char* title) {
int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
buffer[0] = '\0';
return 0;
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index c0ffa564b..ce937cd3e 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -78,11 +78,11 @@ int uv_exepath(char* buffer, size_t* size) {
int err;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mypid = getpid();
for (;;) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size);
if (argsbuf_tmp == NULL)
goto out;
@@ -95,14 +95,14 @@ int uv_exepath(char* buffer, size_t* size) {
break;
}
if (errno != ENOMEM) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
argsbuf_size *= 2U;
}
if (argsbuf[0] == NULL) {
- err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
+ err = UV_EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
goto out;
}
@@ -128,7 +128,7 @@ uint64_t uv_get_free_memory(void) {
int which[] = {CTL_VM, VM_UVMEXP};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
}
@@ -140,7 +140,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -162,7 +162,7 @@ int uv_set_process_title(const char* title) {
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
@@ -179,7 +179,7 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -189,7 +189,7 @@ int uv_get_process_title(char* buffer, size_t size) {
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
@@ -219,7 +219,7 @@ int uv_resident_set_memory(size_t* rss) {
mib[5] = 1;
if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0)
- return -errno;
+ return UV__ERR(errno);
*rss = kinfo.p_vm_rssize * page_size;
return 0;
@@ -233,7 +233,7 @@ int uv_uptime(double* uptime) {
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
@@ -255,16 +255,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctl(which, 2, &model, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
which[1] = HW_NCPU;
size = sizeof(numcpus);
if (sysctl(which, 2, &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
- return -ENOMEM;
+ return UV_ENOMEM;
*count = numcpus;
@@ -272,7 +272,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(info);
@@ -283,7 +283,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
cpu_info = &(*cpu_infos)[i];
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
index 21558ea86..a5dd34426 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -215,6 +215,7 @@ uv__os390_epoll* epoll_create1(int flags) {
maybe_resize(lst, 1);
lst->items[lst->size - 1].fd = lst->msg_queue;
lst->items[lst->size - 1].events = POLLIN;
+ lst->items[lst->size - 1].revents = 0;
uv_once(&once, epoll_init);
uv_mutex_lock(&global_epoll_lock);
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
@@ -252,6 +253,7 @@ int epoll_ctl(uv__os390_epoll* lst,
}
lst->items[fd].fd = fd;
lst->items[fd].events = event->events;
+ lst->items[fd].revents = 0;
} else if (op == EPOLL_CTL_MOD) {
if (fd >= lst->size || lst->items[fd].fd == -1) {
uv_mutex_unlock(&global_epoll_lock);
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index 081438e8e..f766b3933 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -122,7 +122,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
ep = epoll_create1(0);
loop->ep = ep;
if (ep == NULL)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -259,12 +259,12 @@ int uv_exepath(char* buffer, size_t* size) {
int pid;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
pid = getpid();
res = getexe(pid, args, sizeof(args));
if (res < 0)
- return -EINVAL;
+ return UV_EINVAL;
/*
* Possibilities for args:
@@ -277,7 +277,7 @@ int uv_exepath(char* buffer, size_t* size) {
/* Case i) and ii) absolute or relative paths */
if (strchr(args, '/') != NULL) {
if (realpath(args, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
@@ -297,11 +297,11 @@ int uv_exepath(char* buffer, size_t* size) {
char* path = getenv("PATH");
if (path == NULL)
- return -EINVAL;
+ return UV_EINVAL;
clonedpath = uv__strdup(path);
if (clonedpath == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
token = strtok(clonedpath, ":");
while (token != NULL) {
@@ -327,7 +327,7 @@ int uv_exepath(char* buffer, size_t* size) {
uv__free(clonedpath);
/* Out of tokens (path entries), and no match found */
- return -EINVAL;
+ return UV_EINVAL;
}
}
@@ -407,7 +407,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t));
if (!*cpu_infos)
- return -ENOMEM;
+ return UV_ENOMEM;
cpu_info = *cpu_infos;
idx = 0;
@@ -452,7 +452,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
maxsize = 16384;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
- return -errno;
+ return UV__ERR(errno);
ifc.__nif6h_version = 1;
ifc.__nif6h_buflen = maxsize;
@@ -460,7 +460,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
@@ -484,7 +484,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
@@ -543,13 +543,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (0 > sockfd)
- return -errno;
+ return UV__ERR(errno);
ifc.ifc_req = uv__calloc(1, maxsize);
ifc.ifc_len = maxsize;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
@@ -569,7 +569,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -584,7 +584,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
@@ -607,7 +607,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -706,7 +706,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
int rc;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
ep = handle->loop->ep;
assert(ep->msg_queue != -1);
@@ -718,11 +718,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
path = uv__strdup(filename);
if (path == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
if (rc != 0)
- return -errno;
+ return UV__ERR(errno);
uv__handle_start(handle);
handle->path = path;
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index df3aad036..42846b927 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -48,12 +48,12 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Already bound? */
if (uv__stream_fd(handle) >= 0)
- return -EINVAL;
+ return UV_EINVAL;
/* Make a copy of the file name, it outlives this function's scope. */
pipe_fname = uv__strdup(name);
if (pipe_fname == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
/* We've got a copy, don't touch the original any more. */
name = NULL;
@@ -69,10 +69,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
saddr.sun_family = AF_UNIX;
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
- err = -errno;
+ err = UV__ERR(errno);
/* Convert ENOENT to EACCES for compatibility with Windows. */
- if (err == -ENOENT)
- err = -EACCES;
+ if (err == UV_ENOENT)
+ err = UV_EACCES;
uv__close(sockfd);
goto err_socket;
@@ -92,7 +92,7 @@ err_socket:
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
if (uv__stream_fd(handle) == -1)
- return -EINVAL;
+ return UV_EINVAL;
#if defined(__MVS__)
/* On zOS, backlog=0 has undefined behaviour */
@@ -103,7 +103,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
#endif
if (listen(uv__stream_fd(handle), backlog))
- return -errno;
+ return UV__ERR(errno);
handle->connection_cb = cb;
handle->io_watcher.cb = uv__server_io;
@@ -178,14 +178,14 @@ void uv_pipe_connect(uv_connect_t* req,
while (r == -1 && errno == EINTR);
if (r == -1 && errno != EINPROGRESS) {
- err = -errno;
+ err = UV__ERR(errno);
#if defined(__CYGWIN__) || defined(__MSYS__)
/* EBADF is supposed to mean that the socket fd is bad, but
Cygwin reports EBADF instead of ENOTSOCK when the file is
not a socket. We do not expect to see a bad fd here
(e.g. due to new_sock), so translate the error. */
- if (err == -EBADF)
- err = -ENOTSOCK;
+ if (err == UV_EBADF)
+ err = UV_ENOTSOCK;
#endif
goto out;
}
@@ -232,7 +232,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
if (err < 0) {
*size = 0;
- return -errno;
+ return UV__ERR(errno);
}
#if defined(__linux__)
@@ -310,27 +310,12 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
int r;
if (handle == NULL || uv__stream_fd(handle) == -1)
- return -EBADF;
+ return UV_EBADF;
if (mode != UV_READABLE &&
mode != UV_WRITABLE &&
mode != (UV_WRITABLE | UV_READABLE))
- return -EINVAL;
-
- if (fstat(uv__stream_fd(handle), &pipe_stat) == -1)
- return -errno;
-
- desired_mode = 0;
- if (mode & UV_READABLE)
- desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
- if (mode & UV_WRITABLE)
- desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- /* Exit early if pipe already has desired mode. */
- if ((pipe_stat.st_mode & desired_mode) == desired_mode)
- return 0;
-
- pipe_stat.st_mode |= desired_mode;
+ return UV_EINVAL;
/* Unfortunately fchmod does not work on all platforms, we will use chmod. */
name_len = 0;
@@ -348,8 +333,28 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
return r;
}
+ /* stat must be used as fstat has a bug on Darwin */
+ if (stat(name_buffer, &pipe_stat) == -1) {
+ uv__free(name_buffer);
+ return -errno;
+ }
+
+ desired_mode = 0;
+ if (mode & UV_READABLE)
+ desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
+ if (mode & UV_WRITABLE)
+ desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ /* Exit early if pipe already has desired mode. */
+ if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
+ uv__free(name_buffer);
+ return 0;
+ }
+
+ pipe_stat.st_mode |= desired_mode;
+
r = chmod(name_buffer, pipe_stat.st_mode);
uv__free(name_buffer);
- return r != -1 ? 0 : -errno;
+ return r != -1 ? 0 : UV__ERR(errno);
}
diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c
index 816c7dc2e..f3b0bf4e4 100644
--- a/Utilities/cmlibuv/src/unix/poll.c
+++ b/Utilities/cmlibuv/src/unix/poll.c
@@ -47,7 +47,7 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
if ((events & POLLERR) && !(events & UV__POLLPRI)) {
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
uv__handle_stop(handle);
- handle->poll_cb(handle, -EBADF, 0);
+ handle->poll_cb(handle, UV_EBADF, 0);
return;
}
@@ -76,7 +76,7 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
* Workaround for e.g. kqueue fds not supporting ioctls.
*/
err = uv__nonblock(fd, 1);
- if (err == -ENOTTY)
+ if (err == UV_ENOTTY)
if (uv__nonblock == uv__nonblock_ioctl)
err = uv__nonblock_fcntl(fd, 1);
diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c
index 3fba96e1b..f3181f9b7 100644
--- a/Utilities/cmlibuv/src/unix/posix-poll.c
+++ b/Utilities/cmlibuv/src/unix/posix-poll.c
@@ -107,7 +107,7 @@ static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) {
static void uv__pollfds_del(uv_loop_t* loop, int fd) {
size_t i;
assert(!loop->poll_fds_iterating);
- for (i = 0; i < loop->poll_fds_used; ++i) {
+ for (i = 0; i < loop->poll_fds_used;) {
if (loop->poll_fds[i].fd == fd) {
/* swap to last position and remove */
--loop->poll_fds_used;
@@ -115,7 +115,17 @@ static void uv__pollfds_del(uv_loop_t* loop, int fd) {
loop->poll_fds[loop->poll_fds_used].fd = -1;
loop->poll_fds[loop->poll_fds_used].events = 0;
loop->poll_fds[loop->poll_fds_used].revents = 0;
- return;
+ /* This method is called with an fd of -1 to purge the invalidated fds,
+ * so we may possibly have multiples to remove.
+ */
+ if (-1 != fd)
+ return;
+ } else {
+ /* We must only increment the loop counter when the fds do not match.
+ * Otherwise, when we are purging an invalidated fd, the value just
+ * swapped here from the previous end of the array will be skipped.
+ */
+ ++i;
}
}
}
@@ -315,10 +325,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
while (rv == -1 && (errno == EINTR || errno == EAGAIN));
if (rv == -1)
- return -errno;
+ return UV__ERR(errno);
if (p[0].revents & POLLNVAL)
- return -EINVAL;
+ return UV_EINVAL;
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index 9842710d0..1bded8d38 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -32,6 +32,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
+#include <sched.h>
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <crt_externs.h>
@@ -44,6 +45,16 @@ extern char **environ;
# include <grp.h>
#endif
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__)
+# define uv__cpu_set_t cpu_set_t
+#elif defined(__FreeBSD__)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+# include <pthread_np.h>
+# define uv__cpu_set_t cpuset_t
+#endif
+#endif
static void uv__chld(uv_signal_t* handle, int signum) {
uv_process_t* process;
@@ -126,7 +137,7 @@ int uv__make_socketpair(int fds[2], int flags) {
* Anything else is a genuine error.
*/
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
no_cloexec = 1;
@@ -134,7 +145,7 @@ skip:
#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
@@ -159,7 +170,7 @@ int uv__make_pipe(int fds[2], int flags) {
return 0;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_pipe2 = 1;
@@ -167,7 +178,7 @@ skip:
#endif
if (pipe(fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
@@ -198,7 +209,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
case UV_CREATE_PIPE:
assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE)
- return -EINVAL;
+ return UV_EINVAL;
else
return uv__make_socketpair(fds, 0);
@@ -210,21 +221,20 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
fd = uv__stream_fd(container->data.stream);
if (fd == -1)
- return -EINVAL;
+ return UV_EINVAL;
fds[1] = fd;
return 0;
default:
assert(0 && "Unexpected flags");
- return -EINVAL;
+ return UV_EINVAL;
}
}
static int uv__process_open_stream(uv_stdio_container_t* container,
- int pipefds[2],
- int writable) {
+ int pipefds[2]) {
int flags;
int err;
@@ -238,13 +248,11 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
pipefds[1] = -1;
uv__nonblock(pipefds[0], 1);
- if (container->data.stream->type == UV_NAMED_PIPE &&
- ((uv_pipe_t*)container->data.stream)->ipc)
- flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE;
- else if (writable)
- flags = UV_STREAM_WRITABLE;
- else
- flags = UV_STREAM_READABLE;
+ flags = 0;
+ if (container->flags & UV_WRITABLE_PIPE)
+ flags |= UV_STREAM_READABLE;
+ if (container->flags & UV_READABLE_PIPE)
+ flags |= UV_STREAM_WRITABLE;
return uv__stream_open(container->data.stream, pipefds[0], flags);
}
@@ -285,6 +293,14 @@ static void uv__process_child_init(const uv_process_options_t* options,
int err;
int fd;
int n;
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ int r;
+ int i;
+ int cpumask_size;
+ uv__cpu_set_t cpuset;
+#endif
+#endif
if (options->flags & UV_PROCESS_DETACHED)
setsid();
@@ -299,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
continue;
pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
if (pipes[fd][1] == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
@@ -319,7 +335,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
close_fd = use_fd;
if (use_fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
@@ -331,7 +347,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
fd = dup2(use_fd, fd);
if (fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -350,7 +366,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if (options->cwd != NULL && chdir(options->cwd)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -366,15 +382,37 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask != NULL) {
+ cpumask_size = uv_cpumask_size();
+ assert(options->cpumask_size >= (size_t)cpumask_size);
+
+ CPU_ZERO(&cpuset);
+ for (i = 0; i < cpumask_size; ++i) {
+ if (options->cpumask[i]) {
+ CPU_SET(i, &cpuset);
+ }
+ }
+
+ r = -pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+ if (r != 0) {
+ uv__write_int(error_fd, r);
+ _exit(127);
+ }
+ }
+#endif
+#endif
+
if (options->env != NULL) {
environ = options->env;
}
@@ -391,7 +429,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
if (SIG_ERR != signal(n, SIG_DFL))
continue;
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -400,12 +438,12 @@ static void uv__process_child_init(const uv_process_options_t* options,
err = pthread_sigmask(SIG_SETMASK, &set, NULL);
if (err != 0) {
- uv__write_int(error_fd, -err);
+ uv__write_int(error_fd, UV__ERR(err));
_exit(127);
}
execvp(options->file, options->args);
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
#endif
@@ -416,7 +454,7 @@ int uv_spawn(uv_loop_t* loop,
const uv_process_options_t* options) {
#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
- return -ENOSYS;
+ return UV_ENOSYS;
#else
int signal_pipe[2] = { -1, -1 };
int pipes_storage[8][2];
@@ -429,6 +467,20 @@ int uv_spawn(uv_loop_t* loop,
int i;
int status;
+ if (options->cpumask != NULL) {
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+#else
+ return UV_ENOTSUP;
+#endif
+#else
+ return UV_ENOTSUP;
+#endif
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
@@ -443,7 +495,7 @@ int uv_spawn(uv_loop_t* loop,
if (stdio_count < 3)
stdio_count = 3;
- err = -ENOMEM;
+ err = UV_ENOMEM;
pipes = pipes_storage;
if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
pipes = uv__malloc(stdio_count * sizeof(*pipes));
@@ -493,7 +545,7 @@ int uv_spawn(uv_loop_t* loop,
pid = fork();
if (pid == -1) {
- err = -errno;
+ err = UV__ERR(errno);
uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[0]);
uv__close(signal_pipe[1]);
@@ -533,7 +585,7 @@ int uv_spawn(uv_loop_t* loop,
uv__close_nocheckstdio(signal_pipe[0]);
for (i = 0; i < options->stdio_count; i++) {
- err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
+ err = uv__process_open_stream(options->stdio + i, pipes[i]);
if (err == 0)
continue;
@@ -585,7 +637,7 @@ int uv_process_kill(uv_process_t* process, int signum) {
int uv_kill(int pid, int signum) {
if (kill(pid, signum))
- return -errno;
+ return UV__ERR(errno);
else
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/procfs-exepath.c b/Utilities/cmlibuv/src/unix/procfs-exepath.c
index 5fdb61155..00dc021f2 100644
--- a/Utilities/cmlibuv/src/unix/procfs-exepath.c
+++ b/Utilities/cmlibuv/src/unix/procfs-exepath.c
@@ -29,14 +29,14 @@ int uv_exepath(char* buffer, size_t* size) {
ssize_t n;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
n = *size - 1;
if (n > 0)
n = readlink("/proc/self/exe", buffer, n);
if (n == -1)
- return -errno;
+ return UV__ERR(errno);
buffer[n] = '\0';
*size = n;
diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c
index 1b3a79882..1a8c7a709 100644
--- a/Utilities/cmlibuv/src/unix/proctitle.c
+++ b/Utilities/cmlibuv/src/unix/proctitle.c
@@ -105,14 +105,14 @@ int uv_set_process_title(const char* title) {
int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (size <= process_title.len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
if (process_title.len != 0)
diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c
index 375977801..b9d0a5608 100644
--- a/Utilities/cmlibuv/src/unix/signal.c
+++ b/Utilities/cmlibuv/src/unix/signal.c
@@ -225,7 +225,7 @@ static int uv__signal_register_handler(int signum, int oneshot) {
/* XXX save old action so we can restore it later on? */
if (sigaction(signum, &sa, NULL))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -362,7 +362,7 @@ static int uv__signal_start(uv_signal_t* handle,
* eventually.
*/
if (signum == 0)
- return -EINVAL;
+ return UV_EINVAL;
/* Short circuit: if the signal watcher is already watching {signum} don't
* go through the process of deregistering and registering the handler.
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 931e5f1ce..9bdd1c507 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -58,6 +58,12 @@ struct uv__stream_select_s {
fd_set* swrite;
size_t swrite_sz;
};
+# define WRITE_RETRY_ON_ERROR(send_handle) \
+ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
+ (errno == EMSGSIZE && send_handle))
+#else
+# define WRITE_RETRY_ON_ERROR(send_handle) \
+ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
#endif /* defined(__APPLE__) */
static void uv__stream_connect(uv_stream_t*);
@@ -282,7 +288,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
kq = kqueue();
if (kq == -1) {
perror("(libuv) kqueue()");
- return -errno;
+ return UV__ERR(errno);
}
EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
@@ -298,7 +304,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
uv__close(kq);
if (ret == -1)
- return -errno;
+ return UV__ERR(errno);
if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL)
return 0;
@@ -310,7 +316,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
* NOTE: do it ahead of malloc below to allocate enough space for fd_sets
*/
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
max_fd = *fd;
if (fds[1] > max_fd)
@@ -321,7 +327,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
if (s == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto failed_malloc;
}
@@ -395,18 +401,18 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
#endif
if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
- return -EBUSY;
+ return UV_EBUSY;
assert(fd >= 0);
stream->flags |= flags;
if (stream->type == UV_TCP) {
if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
- return -errno;
+ return UV__ERR(errno);
/* TODO Use delay the user passed in. */
if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60))
- return -errno;
+ return UV__ERR(errno);
}
#if defined(__APPLE__)
@@ -414,7 +420,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
errno != ENOTSOCK &&
errno != EINVAL) {
- return -errno;
+ return UV__ERR(errno);
}
#endif
@@ -445,11 +451,11 @@ void uv__stream_destroy(uv_stream_t* stream) {
if (stream->connect_req) {
uv__req_unregister(stream->loop, stream->connect_req);
- stream->connect_req->cb(stream->connect_req, -ECANCELED);
+ stream->connect_req->cb(stream->connect_req, UV_ECANCELED);
stream->connect_req = NULL;
}
- uv__stream_flush_write_queue(stream, -ECANCELED);
+ uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
if (stream->shutdown_req) {
@@ -459,7 +465,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
* callee that the handle has been destroyed.
*/
uv__req_unregister(stream->loop, stream->shutdown_req);
- stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED);
+ stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
stream->shutdown_req = NULL;
}
@@ -483,7 +489,7 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
int emfile_fd;
if (loop->emfile_fd == -1)
- return -EMFILE;
+ return UV_EMFILE;
uv__close(loop->emfile_fd);
loop->emfile_fd = -1;
@@ -492,7 +498,7 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
err = uv__accept(accept_fd);
if (err >= 0)
uv__close(err);
- } while (err >= 0 || err == -EINTR);
+ } while (err >= 0 || err == UV_EINTR);
emfile_fd = uv__open_cloexec("/", O_RDONLY);
if (emfile_fd >= 0)
@@ -533,15 +539,15 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
err = uv__accept(uv__stream_fd(stream));
if (err < 0) {
- if (err == -EAGAIN || err == -EWOULDBLOCK)
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
return; /* Not an error. */
- if (err == -ECONNABORTED)
+ if (err == UV_ECONNABORTED)
continue; /* Ignore. Nothing we can do about that. */
- if (err == -EMFILE || err == -ENFILE) {
+ if (err == UV_EMFILE || err == UV_ENFILE) {
err = uv__emfile_trick(loop, uv__stream_fd(stream));
- if (err == -EAGAIN || err == -EWOULDBLOCK)
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
break;
}
@@ -577,7 +583,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
assert(server->loop == client->loop);
if (server->accepted_fd == -1)
- return -EAGAIN;
+ return UV_EAGAIN;
switch (client->type) {
case UV_NAMED_PIPE:
@@ -601,7 +607,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
client->flags |= UV_HANDLE_BOUND;
@@ -649,7 +655,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
break;
default:
- err = -EINVAL;
+ err = UV_EINVAL;
}
if (err == 0)
@@ -680,7 +686,7 @@ static void uv__drain(uv_stream_t* stream) {
err = 0;
if (shutdown(uv__stream_fd(stream), SHUT_WR))
- err = -errno;
+ err = UV__ERR(errno);
if (err == 0)
stream->flags |= UV_STREAM_SHUT;
@@ -792,7 +798,7 @@ start:
} scratch;
if (uv__is_closing(req->send_handle)) {
- err = -EBADF;
+ err = UV_EBADF;
goto error;
}
@@ -859,8 +865,8 @@ start:
}
if (n < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENOBUFS) {
- err = -errno;
+ if (!WRITE_RETRY_ON_ERROR(req->send_handle)) {
+ err = UV__ERR(errno);
goto error;
} else if (stream->flags & UV_STREAM_BLOCKING) {
/* If this is a blocking stream, try again. */
@@ -1029,7 +1035,7 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
sizeof(*queued_fds));
if (queued_fds == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
queued_fds->size = queue_size;
queued_fds->offset = 0;
stream->queued_fds = queued_fds;
@@ -1046,7 +1052,7 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
* NOTE: if it is fatal - sockets will be closed in uv__stream_close
*/
if (queued_fds == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
queued_fds->size = queue_size;
stream->queued_fds = queued_fds;
}
@@ -1192,7 +1198,7 @@ static void uv__read(uv_stream_t* stream) {
#endif
} else {
/* Error. User should call uv_close(). */
- stream->read_cb(stream, -errno, &buf);
+ stream->read_cb(stream, UV__ERR(errno), &buf);
if (stream->flags & UV_STREAM_READING) {
stream->flags &= ~UV_STREAM_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
@@ -1269,7 +1275,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
stream->flags & UV_STREAM_SHUT ||
stream->flags & UV_STREAM_SHUTTING ||
uv__is_closing(stream)) {
- return -ENOTCONN;
+ return UV_ENOTCONN;
}
assert(uv__stream_fd(stream) >= 0);
@@ -1368,10 +1374,10 @@ static void uv__stream_connect(uv_stream_t* stream) {
SO_ERROR,
&error,
&errorsize);
- error = -error;
+ error = UV__ERR(error);
}
- if (error == -EINPROGRESS)
+ if (error == UV__ERR(EINPROGRESS))
return;
stream->connect_req = NULL;
@@ -1388,7 +1394,7 @@ static void uv__stream_connect(uv_stream_t* stream) {
return;
if (error < 0) {
- uv__stream_flush_write_queue(stream, -ECANCELED);
+ uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
}
}
@@ -1409,11 +1415,14 @@ int uv_write2(uv_write_t* req,
"uv_write (unix) does not yet support other types of streams");
if (uv__stream_fd(stream) < 0)
- return -EBADF;
+ return UV_EBADF;
+
+ if (!(stream->flags & UV_STREAM_WRITABLE))
+ return -EPIPE;
if (send_handle) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
- return -EINVAL;
+ return UV_EINVAL;
/* XXX We abuse uv_write2() to send over UDP handles to child processes.
* Don't call uv__stream_fd() on those handles, it's a macro that on OS X
@@ -1422,12 +1431,12 @@ int uv_write2(uv_write_t* req,
* which works but only by accident.
*/
if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
- return -EBADF;
+ return UV_EBADF;
#if defined(__CYGWIN__) || defined(__MSYS__)
/* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -1452,7 +1461,7 @@ int uv_write2(uv_write_t* req,
req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
if (req->bufs == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
req->nbufs = nbufs;
@@ -1516,7 +1525,7 @@ int uv_try_write(uv_stream_t* stream,
/* Connecting or already writing some data */
if (stream->connect_req != NULL || stream->write_queue_size != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
@@ -1547,7 +1556,7 @@ int uv_try_write(uv_stream_t* stream,
}
if (written == 0 && req_size != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
else
return written;
}
@@ -1560,7 +1569,10 @@ int uv_read_start(uv_stream_t* stream,
stream->type == UV_TTY);
if (stream->flags & UV_CLOSING)
- return -EINVAL;
+ return UV_EINVAL;
+
+ if (!(stream->flags & UV_STREAM_READABLE))
+ return -ENOTCONN;
/* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index d6f952732..b92888e10 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -77,7 +77,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
fd = port_create();
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
@@ -136,7 +136,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
int uv__io_check_fd(uv_loop_t* loop, int fd) {
if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
- return -errno;
+ return UV__ERR(errno);
if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
abort();
@@ -346,7 +346,7 @@ int uv_exepath(char* buffer, size_t* size) {
char buf[128];
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid());
@@ -355,7 +355,7 @@ int uv_exepath(char* buffer, size_t* size) {
res = readlink(buf, buffer, res);
if (res == -1)
- return -errno;
+ return UV__ERR(errno);
buffer[res] = '\0';
*size = res;
@@ -382,14 +382,14 @@ void uv_loadavg(double avg[3]) {
static int uv__fs_event_rearm(uv_fs_event_t *handle) {
if (handle->fd == -1)
- return -EBADF;
+ return UV_EBADF;
if (port_associate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
(uintptr_t) &handle->fo,
FILE_ATTRIB | FILE_MODIFIED,
handle) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
handle->fd = PORT_LOADED;
@@ -466,13 +466,13 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int err;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
first_run = 0;
if (handle->loop->fs_fd == -1) {
portfd = port_create();
if (portfd == -1)
- return -errno;
+ return UV__ERR(errno);
handle->loop->fs_fd = portfd;
first_run = 1;
}
@@ -525,7 +525,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
#else /* !defined(PORT_SOURCE_FILE) */
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
@@ -533,12 +533,12 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* filename,
unsigned int flags) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
@@ -556,10 +556,10 @@ int uv_resident_set_memory(size_t* rss) {
fd = open("/proc/self/psinfo", O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
/* FIXME(bnoordhuis) Handle EINTR. */
- err = -EINVAL;
+ err = UV_EINVAL;
if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
*rss = (size_t)psinfo.pr_rssize * 1024;
err = 0;
@@ -579,7 +579,7 @@ int uv_uptime(double* uptime) {
kc = kstat_open();
if (kc == NULL)
- return -EPERM;
+ return UV_EPERM;
ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc");
if (kstat_read(kc, ksp, NULL) == -1) {
@@ -603,7 +603,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
kc = kstat_open();
if (kc == NULL)
- return -EPERM;
+ return UV_EPERM;
/* Get count of cpus */
lookup_instance = 0;
@@ -614,7 +614,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
kstat_close(kc);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = lookup_instance;
@@ -696,7 +696,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
#ifdef SUNOS_NO_IFADDRS
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
#else /* SUNOS_NO_IFADDRS */
/*
@@ -734,11 +734,11 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
- return -errno;
+ return UV__ERR(errno);
if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr));
uv__close(sockfd);
@@ -763,7 +763,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs* ent;
if (getifaddrs(&addrs))
- return -errno;
+ return UV__ERR(errno);
*count = 0;
@@ -777,7 +777,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c
index c7c8d21c6..9a46793fd 100644
--- a/Utilities/cmlibuv/src/unix/tcp.c
+++ b/Utilities/cmlibuv/src/unix/tcp.c
@@ -49,16 +49,14 @@ static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
/* Bind this new socket to an arbitrary port */
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
- err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen);
- if (err) {
+ if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
uv__close(sockfd);
- return err;
+ return UV__ERR(errno);
}
- err = bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen);
- if (err) {
+ if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
uv__close(sockfd);
- return err;
+ return UV__ERR(errno);
}
}
@@ -89,7 +87,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
- return -errno;
+ return UV__ERR(errno);
if ((saddr.ss_family == AF_INET6 &&
((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
@@ -102,7 +100,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
/* Bind to arbitrary port */
if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
- return -errno;
+ return UV__ERR(errno);
}
handle->flags |= flags;
@@ -119,10 +117,10 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
/* Use the lower 8 bits for the domain */
domain = flags & 0xFF;
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return -EINVAL;
+ return UV_EINVAL;
if (flags & ~0xFF)
- return -EINVAL;
+ return UV_EINVAL;
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
@@ -156,18 +154,17 @@ int uv__tcp_bind(uv_tcp_t* tcp,
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
- return -EINVAL;
+ return UV_EINVAL;
- err = maybe_new_socket(tcp,
- addr->sa_family,
- UV_STREAM_READABLE | UV_STREAM_WRITABLE);
+ err = maybe_new_socket(tcp, addr->sa_family, 0);
if (err)
return err;
on = 1;
if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
+#ifndef __OpenBSD__
#ifdef IPV6_V6ONLY
if (addr->sa_family == AF_INET6) {
on = (flags & UV_TCP_IPV6ONLY) != 0;
@@ -178,22 +175,23 @@ int uv__tcp_bind(uv_tcp_t* tcp,
sizeof on) == -1) {
#if defined(__MVS__)
if (errno == EOPNOTSUPP)
- return -EINVAL;
+ return UV_EINVAL;
#endif
- return -errno;
+ return UV__ERR(errno);
}
}
#endif
+#endif
errno = 0;
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
- return -EINVAL;
- return -errno;
+ return UV_EINVAL;
+ return UV__ERR(errno);
}
- tcp->delayed_error = -errno;
+ tcp->delayed_error = UV__ERR(errno);
tcp->flags |= UV_HANDLE_BOUND;
if (addr->sa_family == AF_INET6)
@@ -214,7 +212,7 @@ int uv__tcp_connect(uv_connect_t* req,
assert(handle->type == UV_TCP);
if (handle->connect_req != NULL)
- return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */
+ return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
err = maybe_new_socket(handle,
addr->sa_family,
@@ -242,9 +240,9 @@ int uv__tcp_connect(uv_connect_t* req,
* error. Solaris wants to report immediately--other unixes want to
* wait.
*/
- handle->delayed_error = -errno;
+ handle->delayed_error = UV__ERR(errno);
else
- return -errno;
+ return UV__ERR(errno);
}
uv__req_init(handle->loop, req, UV_CONNECT);
@@ -284,13 +282,13 @@ int uv_tcp_getsockname(const uv_tcp_t* handle,
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(uv__stream_fd(handle), name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
@@ -306,13 +304,13 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getpeername(uv__stream_fd(handle), name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
@@ -335,20 +333,20 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
if (single_accept)
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
- flags = UV_STREAM_READABLE;
+ flags = 0;
#if defined(__MVS__)
/* on zOS the listen call does not bind automatically
if the socket is unbound. Hence the manual binding to
an arbitrary port is required to be done manually
*/
flags |= UV_HANDLE_BOUND;
-#endif
+#endif
err = maybe_new_socket(tcp, AF_INET, flags);
if (err)
return err;
if (listen(tcp->io_watcher.fd, backlog))
- return -errno;
+ return UV__ERR(errno);
tcp->connection_cb = cb;
tcp->flags |= UV_HANDLE_BOUND;
@@ -363,18 +361,18 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int uv__tcp_nodelay(int fd, int on) {
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
#ifdef TCP_KEEPIDLE
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
- return -errno;
+ return UV__ERR(errno);
#endif
/* Solaris/SmartOS, if you don't support keep-alive,
@@ -383,7 +381,7 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
#if defined(TCP_KEEPALIVE) && !defined(__sun)
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
- return -errno;
+ return UV__ERR(errno);
#endif
return 0;
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index abaca295d..303bc6ec8 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -37,6 +37,10 @@
#include <sys/sem.h>
#endif
+#ifdef __GLIBC__
+#include <gnu/libc-version.h> /* gnu_get_libc_version() */
+#endif
+
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
@@ -200,7 +204,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
if (attr != NULL)
pthread_attr_destroy(attr);
- return -err;
+ return UV__ERR(err);
}
@@ -209,7 +213,7 @@ uv_thread_t uv_thread_self(void) {
}
int uv_thread_join(uv_thread_t *tid) {
- return -pthread_join(*tid, NULL);
+ return UV__ERR(pthread_join(*tid, NULL));
}
@@ -220,7 +224,7 @@ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
int uv_mutex_init(uv_mutex_t* mutex) {
#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
- return -pthread_mutex_init(mutex, NULL);
+ return UV__ERR(pthread_mutex_init(mutex, NULL));
#else
pthread_mutexattr_t attr;
int err;
@@ -236,7 +240,7 @@ int uv_mutex_init(uv_mutex_t* mutex) {
if (pthread_mutexattr_destroy(&attr))
abort();
- return -err;
+ return UV__ERR(err);
#endif
}
@@ -256,7 +260,7 @@ int uv_mutex_init_recursive(uv_mutex_t* mutex) {
if (pthread_mutexattr_destroy(&attr))
abort();
- return -err;
+ return UV__ERR(err);
}
@@ -279,7 +283,7 @@ int uv_mutex_trylock(uv_mutex_t* mutex) {
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
@@ -293,7 +297,7 @@ void uv_mutex_unlock(uv_mutex_t* mutex) {
int uv_rwlock_init(uv_rwlock_t* rwlock) {
- return -pthread_rwlock_init(rwlock, NULL);
+ return UV__ERR(pthread_rwlock_init(rwlock, NULL));
}
@@ -316,7 +320,7 @@ int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
@@ -342,7 +346,7 @@ int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
@@ -369,12 +373,12 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) {
if (err == KERN_SUCCESS)
return 0;
if (err == KERN_INVALID_ARGUMENT)
- return -EINVAL;
+ return UV_EINVAL;
if (err == KERN_RESOURCE_SHORTAGE)
- return -ENOMEM;
+ return UV_ENOMEM;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
}
@@ -413,115 +417,151 @@ int uv_sem_trywait(uv_sem_t* sem) {
if (err == KERN_SUCCESS)
return 0;
if (err == KERN_OPERATION_TIMED_OUT)
- return -EAGAIN;
+ return UV_EAGAIN;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
+}
+
+#else /* !(defined(__APPLE__) && defined(__MACH__)) */
+
+#ifdef __GLIBC__
+
+/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
+ * by providing a custom implementation for glibc < 2.21 in terms of other
+ * concurrency primitives.
+ * Refs: https://github.com/nodejs/node/issues/19903 */
+
+/* To preserve ABI compatibility, we treat the uv_sem_t as storage for
+ * a pointer to the actual struct we're using underneath. */
+
+static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
+static int platform_needs_custom_semaphore = 0;
+
+static void glibc_version_check(void) {
+ const char* version = gnu_get_libc_version();
+ platform_needs_custom_semaphore =
+ version[0] == '2' && version[1] == '.' &&
+ atoi(version + 2) < 21;
}
#elif defined(__MVS__)
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
- uv_sem_t semid;
+#define platform_needs_custom_semaphore 1
+
+#else /* !defined(__GLIBC__) && !defined(__MVS__) */
+
+#define platform_needs_custom_semaphore 0
+
+#endif
+
+typedef struct uv_semaphore_s {
+ uv_mutex_t mutex;
+ uv_cond_t cond;
+ unsigned int value;
+} uv_semaphore_t;
+
+#if defined(__GLIBC__) || platform_needs_custom_semaphore
+STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
+#endif
+
+static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
int err;
- union {
- int val;
- struct semid_ds* buf;
- unsigned short* array;
- } arg;
+ uv_semaphore_t* sem;
+ sem = uv__malloc(sizeof(*sem));
+ if (sem == NULL)
+ return UV_ENOMEM;
- semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
- if (semid == -1)
- return -errno;
+ if ((err = uv_mutex_init(&sem->mutex)) != 0) {
+ uv__free(sem);
+ return err;
+ }
- arg.val = value;
- if (-1 == semctl(semid, 0, SETVAL, arg)) {
- err = errno;
- if (-1 == semctl(*sem, 0, IPC_RMID))
- abort();
- return -err;
+ if ((err = uv_cond_init(&sem->cond)) != 0) {
+ uv_mutex_destroy(&sem->mutex);
+ uv__free(sem);
+ return err;
}
- *sem = semid;
+ sem->value = value;
+ *(uv_semaphore_t**)sem_ = sem;
return 0;
}
-void uv_sem_destroy(uv_sem_t* sem) {
- if (-1 == semctl(*sem, 0, IPC_RMID))
- abort();
+
+static void uv__custom_sem_destroy(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
+
+ sem = *(uv_semaphore_t**)sem_;
+ uv_cond_destroy(&sem->cond);
+ uv_mutex_destroy(&sem->mutex);
+ uv__free(sem);
}
-void uv_sem_post(uv_sem_t* sem) {
- struct sembuf buf;
- buf.sem_num = 0;
- buf.sem_op = 1;
- buf.sem_flg = 0;
+static void uv__custom_sem_post(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- if (-1 == semop(*sem, &buf, 1))
- abort();
+ sem = *(uv_semaphore_t**)sem_;
+ uv_mutex_lock(&sem->mutex);
+ sem->value++;
+ if (sem->value == 1)
+ uv_cond_signal(&sem->cond);
+ uv_mutex_unlock(&sem->mutex);
}
-void uv_sem_wait(uv_sem_t* sem) {
- struct sembuf buf;
- int op_status;
-
- buf.sem_num = 0;
- buf.sem_op = -1;
- buf.sem_flg = 0;
- do
- op_status = semop(*sem, &buf, 1);
- while (op_status == -1 && errno == EINTR);
+static void uv__custom_sem_wait(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- if (op_status)
- abort();
+ sem = *(uv_semaphore_t**)sem_;
+ uv_mutex_lock(&sem->mutex);
+ while (sem->value == 0)
+ uv_cond_wait(&sem->cond, &sem->mutex);
+ sem->value--;
+ uv_mutex_unlock(&sem->mutex);
}
-int uv_sem_trywait(uv_sem_t* sem) {
- struct sembuf buf;
- int op_status;
- buf.sem_num = 0;
- buf.sem_op = -1;
- buf.sem_flg = IPC_NOWAIT;
+static int uv__custom_sem_trywait(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- do
- op_status = semop(*sem, &buf, 1);
- while (op_status == -1 && errno == EINTR);
+ sem = *(uv_semaphore_t**)sem_;
+ if (uv_mutex_trylock(&sem->mutex) != 0)
+ return UV_EAGAIN;
- if (op_status) {
- if (errno == EAGAIN)
- return -EAGAIN;
- abort();
+ if (sem->value == 0) {
+ uv_mutex_unlock(&sem->mutex);
+ return UV_EAGAIN;
}
+ sem->value--;
+ uv_mutex_unlock(&sem->mutex);
+
return 0;
}
-#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+static int uv__sem_init(uv_sem_t* sem, unsigned int value) {
if (sem_init(sem, 0, value))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
-void uv_sem_destroy(uv_sem_t* sem) {
+static void uv__sem_destroy(uv_sem_t* sem) {
if (sem_destroy(sem))
abort();
}
-void uv_sem_post(uv_sem_t* sem) {
+static void uv__sem_post(uv_sem_t* sem) {
if (sem_post(sem))
abort();
}
-void uv_sem_wait(uv_sem_t* sem) {
+static void uv__sem_wait(uv_sem_t* sem) {
int r;
do
@@ -533,7 +573,7 @@ void uv_sem_wait(uv_sem_t* sem) {
}
-int uv_sem_trywait(uv_sem_t* sem) {
+static int uv__sem_trywait(uv_sem_t* sem) {
int r;
do
@@ -542,20 +582,63 @@ int uv_sem_trywait(uv_sem_t* sem) {
if (r) {
if (errno == EAGAIN)
- return -EAGAIN;
+ return UV_EAGAIN;
abort();
}
return 0;
}
+int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+#ifdef __GLIBC__
+ uv_once(&glibc_version_check_once, glibc_version_check);
+#endif
+
+ if (platform_needs_custom_semaphore)
+ return uv__custom_sem_init(sem, value);
+ else
+ return uv__sem_init(sem, value);
+}
+
+
+void uv_sem_destroy(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_destroy(sem);
+ else
+ uv__sem_destroy(sem);
+}
+
+
+void uv_sem_post(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_post(sem);
+ else
+ uv__sem_post(sem);
+}
+
+
+void uv_sem_wait(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_wait(sem);
+ else
+ uv__sem_wait(sem);
+}
+
+
+int uv_sem_trywait(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ return uv__custom_sem_trywait(sem);
+ else
+ return uv__sem_trywait(sem);
+}
+
#endif /* defined(__APPLE__) && defined(__MACH__) */
#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
int uv_cond_init(uv_cond_t* cond) {
- return -pthread_cond_init(cond, NULL);
+ return UV__ERR(pthread_cond_init(cond, NULL));
}
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
@@ -566,7 +649,7 @@ int uv_cond_init(uv_cond_t* cond) {
err = pthread_condattr_init(&attr);
if (err)
- return -err;
+ return UV__ERR(err);
#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
@@ -588,7 +671,7 @@ error:
pthread_cond_destroy(cond);
error2:
pthread_condattr_destroy(&attr);
- return -err;
+ return UV__ERR(err);
}
#endif /* defined(__APPLE__) && defined(__MACH__) */
@@ -646,13 +729,22 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
int r;
struct timespec ts;
+#if defined(__MVS__)
+ struct timeval tv;
+#endif
#if defined(__APPLE__) && defined(__MACH__)
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
#else
+#if defined(__MVS__)
+ if (gettimeofday(&tv, NULL))
+ abort();
+ timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
+#else
timeout += uv__hrtime(UV_CLOCK_PRECISE);
+#endif
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
@@ -672,15 +764,15 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
return 0;
if (r == ETIMEDOUT)
- return -ETIMEDOUT;
+ return UV_ETIMEDOUT;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
}
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
- return -pthread_barrier_init(barrier, NULL, count);
+ return UV__ERR(pthread_barrier_init(barrier, NULL, count));
}
@@ -699,7 +791,7 @@ int uv_barrier_wait(uv_barrier_t* barrier) {
int uv_key_create(uv_key_t* key) {
- return -pthread_key_create(key, NULL);
+ return UV__ERR(pthread_key_create(key, NULL));
}
diff --git a/Utilities/cmlibuv/src/unix/timer.c b/Utilities/cmlibuv/src/unix/timer.c
index f46bdf4bf..54dabfe7d 100644
--- a/Utilities/cmlibuv/src/unix/timer.c
+++ b/Utilities/cmlibuv/src/unix/timer.c
@@ -66,7 +66,7 @@ int uv_timer_start(uv_timer_t* handle,
uint64_t clamped_timeout;
if (cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (uv__is_active(handle))
uv_timer_stop(handle);
@@ -105,7 +105,7 @@ int uv_timer_stop(uv_timer_t* handle) {
int uv_timer_again(uv_timer_t* handle) {
if (handle->timer_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (handle->repeat) {
uv_timer_stop(handle);
diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c
index fc8c3abf9..e8ea302f2 100644
--- a/Utilities/cmlibuv/src/unix/tty.c
+++ b/Utilities/cmlibuv/src/unix/tty.c
@@ -106,7 +106,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
*/
type = uv_guess_handle(fd);
if (type == UV_FILE || type == UV_UNKNOWN_HANDLE)
- return -EINVAL;
+ return UV_EINVAL;
/* Reopen the file descriptor when it refers to a tty. This lets us put the
* tty in non-blocking mode without affecting other processes that share it
@@ -139,7 +139,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
newfd = r;
r = uv__dup2_cloexec(newfd, fd);
- if (r < 0 && r != -EINVAL) {
+ if (r < 0 && r != UV_EINVAL) {
/* EINVAL means newfd == fd which could conceivably happen if another
* thread called close(fd) between our calls to isatty() and open().
* That's a rather unlikely event but let's handle it anyway.
@@ -160,7 +160,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
if (saved_flags == -1) {
if (newfd != -1)
uv__close(newfd);
- return -errno;
+ return UV__ERR(errno);
}
#endif
@@ -231,7 +231,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
fd = uv__stream_fd(tty);
if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
if (tcgetattr(fd, &tty->orig_termios))
- return -errno;
+ return UV__ERR(errno);
/* This is used for uv_tty_reset_mode() */
uv_spinlock_lock(&termios_spinlock);
@@ -261,7 +261,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
/* Apply changes after draining */
if (tcsetattr(fd, TCSADRAIN, &tmp))
- return -errno;
+ return UV__ERR(errno);
tty->mode = mode;
return 0;
@@ -277,7 +277,7 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
while (err == -1 && errno == EINTR);
if (err == -1)
- return -errno;
+ return UV__ERR(errno);
*width = ws.ws_col;
*height = ws.ws_row;
@@ -355,12 +355,12 @@ int uv_tty_reset_mode(void) {
saved_errno = errno;
if (!uv_spinlock_trylock(&termios_spinlock))
- return -EBUSY; /* In uv_tty_set_mode(). */
+ return UV_EBUSY; /* In uv_tty_set_mode(). */
err = 0;
if (orig_termios_fd != -1)
if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios))
- err = -errno;
+ err = UV__ERR(errno);
uv_spinlock_unlock(&termios_spinlock);
errno = saved_errno;
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index a475bf574..74d613b68 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -72,7 +72,7 @@ void uv__udp_finish_close(uv_udp_t* handle) {
QUEUE_REMOVE(q);
req = QUEUE_DATA(q, uv_udp_send_t, queue);
- req->status = -ECANCELED;
+ req->status = UV_ECANCELED;
QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
}
@@ -189,7 +189,7 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
handle->recv_cb(handle, 0, &buf, NULL, 0);
else
- handle->recv_cb(handle, -errno, &buf, NULL, 0);
+ handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
}
else {
const struct sockaddr *addr;
@@ -242,7 +242,7 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
break;
}
- req->status = (size == -1 ? -errno : size);
+ req->status = (size == -1 ? UV__ERR(errno) : size);
/* Sending a datagram is an atomic operation: either all data
* is written or nothing is (and EMSGSIZE is raised). That is
@@ -270,11 +270,11 @@ static int uv__set_reuse(int fd) {
#if defined(SO_REUSEPORT) && !defined(__linux__)
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
- return -errno;
+ return UV__ERR(errno);
#else
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
- return -errno;
+ return UV__ERR(errno);
#endif
return 0;
@@ -291,11 +291,11 @@ int uv__udp_bind(uv_udp_t* handle,
/* Check for bad flags. */
if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
- return -EINVAL;
+ return UV_EINVAL;
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6)
- return -EINVAL;
+ return UV_EINVAL;
fd = handle->io_watcher.fd;
if (fd == -1) {
@@ -316,21 +316,21 @@ int uv__udp_bind(uv_udp_t* handle,
#ifdef IPV6_V6ONLY
yes = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
return err;
}
#else
- err = -ENOTSUP;
+ err = UV_ENOTSUP;
return err;
#endif
}
if (bind(fd, addr, addrlen)) {
- err = -errno;
+ err = UV__ERR(errno);
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
- err = -EINVAL;
+ err = UV_EINVAL;
return err;
}
@@ -418,7 +418,7 @@ int uv__udp_send(uv_udp_send_t* req,
if (req->bufs == NULL) {
uv__req_unregister(handle->loop, req);
- return -ENOMEM;
+ return UV_ENOMEM;
}
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
@@ -457,7 +457,7 @@ int uv__udp_try_send(uv_udp_t* handle,
/* already sending a message */
if (handle->send_queue_count != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
@@ -475,9 +475,9 @@ int uv__udp_try_send(uv_udp_t* handle,
if (size == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
- return -EAGAIN;
+ return UV_EAGAIN;
else
- return -errno;
+ return UV__ERR(errno);
}
return size;
@@ -512,7 +512,7 @@ static int uv__udp_set_membership4(uv_udp_t* handle,
optname = IP_DROP_MEMBERSHIP;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (setsockopt(handle->io_watcher.fd,
@@ -522,9 +522,9 @@ static int uv__udp_set_membership4(uv_udp_t* handle,
sizeof(mreq))) {
#if defined(__MVS__)
if (errno == ENXIO)
- return -ENODEV;
+ return UV_ENODEV;
#endif
- return -errno;
+ return UV__ERR(errno);
}
return 0;
@@ -543,7 +543,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
if (interface_addr) {
if (uv_ip6_addr(interface_addr, 0, &addr6))
- return -EINVAL;
+ return UV_EINVAL;
mreq.ipv6mr_interface = addr6.sin6_scope_id;
} else {
mreq.ipv6mr_interface = 0;
@@ -559,7 +559,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
optname = IPV6_DROP_MEMBERSHIP;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (setsockopt(handle->io_watcher.fd,
@@ -569,9 +569,9 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
sizeof(mreq))) {
#if defined(__MVS__)
if (errno == ENXIO)
- return -ENODEV;
+ return UV_ENODEV;
#endif
- return -errno;
+ return UV__ERR(errno);
}
return 0;
@@ -586,10 +586,10 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
/* Use the lower 8 bits for the domain */
domain = flags & 0xFF;
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return -EINVAL;
+ return UV_EINVAL;
if (flags & ~0xFF)
- return -EINVAL;
+ return UV_EINVAL;
if (domain != AF_UNSPEC) {
err = uv__socket(domain, SOCK_DGRAM, 0);
@@ -622,7 +622,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
/* Check for already active socket. */
if (handle->io_watcher.fd != -1)
- return -EBUSY;
+ return UV_EBUSY;
err = uv__nonblock(sock, 1);
if (err)
@@ -656,7 +656,7 @@ int uv_udp_set_membership(uv_udp_t* handle,
return err;
return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
} else {
- return -EINVAL;
+ return UV_EINVAL;
}
}
@@ -680,7 +680,7 @@ static int uv__setsockopt(uv_udp_t* handle,
val,
size);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -698,7 +698,7 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle,
#endif
if (val < 0 || val > 255)
- return -EINVAL;
+ return UV_EINVAL;
return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg));
}
@@ -710,7 +710,7 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
SO_BROADCAST,
&on,
sizeof(on))) {
- return -errno;
+ return UV__ERR(errno);
}
return 0;
@@ -719,11 +719,11 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
if (ttl < 1 || ttl > 255)
- return -EINVAL;
+ return UV_EINVAL;
#if defined(__MVS__)
if (!(handle->flags & UV_HANDLE_IPV6))
- return -ENOTSUP; /* zOS does not support setting ttl for IPv4 */
+ return UV_ENOTSUP; /* zOS does not support setting ttl for IPv4 */
#endif
/*
@@ -817,7 +817,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
} else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
/* nothing, address was parsed */
} else {
- return -EINVAL;
+ return UV_EINVAL;
}
if (addr_st.ss_family == AF_INET) {
@@ -826,7 +826,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
IP_MULTICAST_IF,
(void*) &addr4->sin_addr,
sizeof(addr4->sin_addr)) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
} else if (addr_st.ss_family == AF_INET6) {
if (setsockopt(handle->io_watcher.fd,
@@ -834,7 +834,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
IPV6_MULTICAST_IF,
&addr6->sin6_scope_id,
sizeof(addr6->sin6_scope_id)) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
} else {
assert(0 && "unexpected address family");
@@ -851,13 +851,13 @@ int uv_udp_getsockname(const uv_udp_t* handle,
socklen_t socklen;
if (handle->io_watcher.fd == -1)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(handle->io_watcher.fd, name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
@@ -870,10 +870,10 @@ int uv__udp_recv_start(uv_udp_t* handle,
int err;
if (alloc_cb == NULL || recv_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (uv__io_active(&handle->io_watcher, POLLIN))
- return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */
+ return UV_EALREADY; /* FIXME(bnoordhuis) Should be UV_EBUSY. */
err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0);
if (err)
diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c
index fcb910f5f..15dec082f 100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@ -629,7 +629,7 @@ int uv_loop_close(uv_loop_t* loop) {
void* saved_data;
#endif
- if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ if (uv__has_active_reqs(loop))
return UV_EBUSY;
QUEUE_FOREACH(q, &loop->handle_queue) {
diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h
index 781a8559d..c497d014f 100644
--- a/Utilities/cmlibuv/src/uv-common.h
+++ b/Utilities/cmlibuv/src/uv-common.h
@@ -41,6 +41,12 @@
#include "tree.h"
#include "queue.h"
+#if EDOM > 0
+# define UV__ERR(x) (-(x))
+#else
+# define UV__ERR(x) (x)
+#endif
+
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
extern int snprintf(char*, size_t, const char*, ...);
#endif
@@ -127,18 +133,18 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
void uv__fs_scandir_cleanup(uv_fs_t* req);
#define uv__has_active_reqs(loop) \
- (QUEUE_EMPTY(&(loop)->active_reqs) == 0)
+ ((loop)->active_reqs.count > 0)
#define uv__req_register(loop, req) \
do { \
- QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \
+ (loop)->active_reqs.count++; \
} \
while (0)
#define uv__req_unregister(loop, req) \
do { \
assert(uv__has_active_reqs(loop)); \
- QUEUE_REMOVE(&(req)->active_queue); \
+ (loop)->active_reqs.count--; \
} \
while (0)
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 9ed4e824c..b8aad11b7 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -239,7 +239,7 @@ int uv_loop_init(uv_loop_t* loop) {
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->handle_queue);
- QUEUE_INIT(&loop->active_reqs);
+ loop->active_reqs.count = 0;
loop->active_handles = 0;
loop->pending_reqs_tail = NULL;
@@ -470,8 +470,8 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
static int uv__loop_alive(const uv_loop_t* loop) {
- return loop->active_handles > 0 ||
- !QUEUE_EMPTY(&loop->active_reqs) ||
+ return uv__has_active_handles(loop) ||
+ uv__has_active_reqs(loop) ||
loop->endgame_handles != NULL;
}
@@ -603,3 +603,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
return 0;
}
+
+int uv_cpumask_size(void) {
+ return (int)(sizeof(DWORD_PTR) * 8);
+}
diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c
index 95f843ad0..14c9af9ad 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -69,6 +69,7 @@ static void uv_relative_path(const WCHAR* filename,
size_t relpathlen;
size_t filenamelen = wcslen(filename);
size_t dirlen = wcslen(dir);
+ assert(!_wcsnicmp(filename, dir, dirlen));
if (dirlen > 0 && dir[dirlen - 1] == '\\')
dirlen--;
relpathlen = filenamelen - dirlen - 1;
@@ -151,11 +152,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* path,
unsigned int flags) {
- int name_size, is_path_dir;
+ int name_size, is_path_dir, size;
DWORD attr, last_error;
WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
WCHAR short_path_buffer[MAX_PATH];
- WCHAR* short_path;
+ WCHAR* short_path, *long_path;
if (uv__is_active(handle))
return UV_EINVAL;
@@ -197,6 +198,30 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (is_path_dir) {
/* path is a directory, so that's the directory that we will watch. */
+
+ /* Convert to long path. */
+ size = GetLongPathNameW(pathw, NULL, 0);
+
+ if (size) {
+ long_path = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
+ if (!long_path) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
+ }
+
+ size = GetLongPathNameW(pathw, long_path, size);
+ if (size) {
+ long_path[size] = '\0';
+ } else {
+ uv__free(long_path);
+ long_path = NULL;
+ }
+ }
+
+ if (long_path) {
+ uv__free(pathw);
+ pathw = long_path;
+ }
+
dir_to_watch = pathw;
} else {
/*
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 097b00e08..30b87ac51 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -783,7 +783,9 @@ void fs__unlink(uv_fs_t* req) {
/* Remove read-only attribute */
FILE_BASIC_INFORMATION basic = { 0 };
- basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY);
+ basic.FileAttributes = info.dwFileAttributes
+ & ~(FILE_ATTRIBUTE_READONLY)
+ | FILE_ATTRIBUTE_ARCHIVE;
status = pNtSetInformationFile(handle,
&iosb,
@@ -1390,6 +1392,12 @@ static void fs__copyfile(uv_fs_t* req) {
int overwrite;
flags = req->fs.info.file_flags;
+
+ if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
+ return;
+ }
+
overwrite = flags & UV_FS_COPYFILE_EXCL;
if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {
@@ -2334,8 +2342,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
INIT(UV_FS_COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
return UV_EINVAL;
+ }
err = fs__capture_path(req, path, new_path, cb != NULL);
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index 282d919cf..5adc7663b 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -392,15 +392,21 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
DWORD bufsize;
int r;
+ uv__once_init();
+
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
- r = ConvertInterfaceIndexToLuid(ifindex, &luid);
+ if (pConvertInterfaceIndexToLuid == NULL)
+ return UV_ENOSYS;
+ r = pConvertInterfaceIndexToLuid(ifindex, &luid);
if (r != 0)
return uv_translate_sys_error(r);
- r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
+ if (pConvertInterfaceLuidToNameW == NULL)
+ return UV_ENOSYS;
+ r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
if (r != 0)
return uv_translate_sys_error(r);
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 9f28f77e6..849bc8290 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -225,10 +225,16 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* req);
void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
uv_write_t* req);
-/* TODO: remove me */
+/*
+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req);
-/* TODO: remove me */
+/*
+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req);
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index 1a7c4dc15..83ee4f99c 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -735,6 +735,13 @@ void uv__pipe_unpause_read(uv_pipe_t* handle) {
void uv__pipe_stop_read(uv_pipe_t* handle) {
+ if (pCancelIoEx &&
+ !(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) &&
+ !(handle->flags & UV_HANDLE_EMULATE_IOCP) &&
+ handle->flags & UV_HANDLE_READING &&
+ handle->read_req.type == UV_READ) {
+ pCancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
+ }
handle->flags &= ~UV_HANDLE_READING;
uv__pipe_pause_read((uv_pipe_t*)handle);
uv__pipe_unpause_read((uv_pipe_t*)handle);
@@ -847,6 +854,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
return;
}
+ /* Wait for completion via IOCP */
handle->reqs_pending++;
}
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index cc06d9e22..25cfe87c4 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -954,6 +954,12 @@ int uv_spawn(uv_loop_t* loop,
return UV_EINVAL;
}
+ if (options->cpumask != NULL) {
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
@@ -1061,11 +1067,16 @@ int uv_spawn(uv_loop_t* loop,
process_flags = CREATE_UNICODE_ENVIRONMENT;
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
+ /* Avoid creating console window if stdio is not inherited. */
+ for (i = 0; i < options->stdio_count; i++) {
+ if (options->stdio[i].flags & UV_INHERIT_FD)
+ break;
+ if (i == options->stdio_count - 1)
+ process_flags |= CREATE_NO_WINDOW;
+ }
+
/* Use SW_HIDE to avoid any potential process window. */
startup.wShowWindow = SW_HIDE;
-
- /* Hide console windows. */
- process_flags |= CREATE_NO_WINDOW;
} else {
startup.wShowWindow = SW_SHOWDEFAULT;
}
@@ -1084,6 +1095,12 @@ int uv_spawn(uv_loop_t* loop,
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
}
+ if (options->cpumask != NULL) {
+ /* Create the child in a suspended state so we have a chance to set
+ its process affinity before it runs. */
+ process_flags |= CREATE_SUSPENDED;
+ }
+
if (!CreateProcessW(application_path,
arguments,
NULL,
@@ -1099,6 +1116,50 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
+ if (options->cpumask != NULL) {
+ /* The child is currently suspended. Set its process affinity
+ or terminate it if we can't. */
+ int i;
+ int cpumasksize;
+ DWORD_PTR sysmask;
+ DWORD_PTR oldmask;
+ DWORD_PTR newmask;
+
+ cpumasksize = uv_cpumask_size();
+
+ if (!GetProcessAffinityMask(info.hProcess, &oldmask, &sysmask)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+
+ newmask = 0;
+ for (i = 0; i < cpumasksize; i++) {
+ if (options->cpumask[i]) {
+ if (oldmask & (((DWORD_PTR)1) << i)) {
+ newmask |= ((DWORD_PTR)1) << i;
+ } else {
+ err = UV_EINVAL;
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+ }
+ }
+
+ if (!SetProcessAffinityMask(info.hProcess, newmask)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+
+ /* The process affinity of the child is set. Let it run. */
+ if (ResumeThread(info.hThread) == ((DWORD)-1)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+ }
+
/* Spawn succeeded */
/* Beyond this point, failure is reported asynchronously. */
diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h
index dba037470..40f5ddd51 100644
--- a/Utilities/cmlibuv/src/win/stream-inl.h
+++ b/Utilities/cmlibuv/src/win/stream-inl.h
@@ -37,11 +37,6 @@ INLINE static void uv_stream_init(uv_loop_t* loop,
handle->write_queue_size = 0;
handle->activecnt = 0;
handle->stream.conn.shutdown_req = NULL;
-}
-
-
-INLINE static void uv_connection_init(uv_stream_t* handle) {
- handle->flags |= UV_HANDLE_CONNECTION;
handle->stream.conn.write_reqs_pending = 0;
UV_REQ_INIT(&handle->read_req, UV_READ);
@@ -51,4 +46,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
}
+INLINE static void uv_connection_init(uv_stream_t* handle) {
+ handle->flags |= UV_HANDLE_CONNECTION;
+}
+
+
#endif /* UV_WIN_STREAM_INL_H_ */
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index fd6efbaf8..39c1ff056 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -459,8 +459,6 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
- handle->reqs_pending++;
- return;
}
} else {
/* Make this req pending reporting an error. */
@@ -1173,11 +1171,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
err = 0;
if (REQ_SUCCESS(req)) {
- if (setsockopt(handle->socket,
- SOL_SOCKET,
- SO_UPDATE_CONNECT_CONTEXT,
- NULL,
- 0) == 0) {
+ if (handle->flags & UV__HANDLE_CLOSING) {
+ /* use UV_ECANCELED for consistency with Unix */
+ err = ERROR_OPERATION_ABORTED;
+ } else if (setsockopt(handle->socket,
+ SOL_SOCKET,
+ SO_UPDATE_CONNECT_CONTEXT,
+ NULL,
+ 0) == 0) {
uv_connection_init((uv_stream_t*)handle);
handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
loop->active_tcp_streams++;
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 05a11e883..ecf7bc9b5 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -2235,14 +2235,20 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
}
-/* TODO: remove me */
+/*
+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req) {
abort();
}
-/* TODO: remove me */
+/*
+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req) {
abort();
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 3100bc23a..49b5bc720 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -37,7 +37,7 @@
#include <tlhelp32.h>
#include <windows.h>
#include <userenv.h>
-
+#include <math.h>
/*
* Max title length; the only thing MSDN tells us about the maximum length
@@ -587,8 +587,8 @@ int uv_uptime(double* uptime) {
BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
counter_definition->CounterOffset;
uint64_t value = *((uint64_t*) address);
- *uptime = (double) (object_type->PerfTime.QuadPart - value) /
- (double) object_type->PerfFreq.QuadPart;
+ *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /
+ (double) object_type->PerfFreq.QuadPart);
uv__free(malloced_buffer);
return 0;
}
@@ -615,7 +615,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
DWORD sppi_size;
SYSTEM_INFO system_info;
- DWORD cpu_count, r, i;
+ DWORD cpu_count, i;
NTSTATUS status;
ULONG result_size;
int err;
@@ -670,34 +670,33 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
assert(len > 0 && len < ARRAY_SIZE(key_name));
- r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- key_name,
- 0,
- KEY_QUERY_VALUE,
- &processor_key);
- if (r != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ key_name,
+ 0,
+ KEY_QUERY_VALUE,
+ &processor_key);
+ if (err != ERROR_SUCCESS) {
goto error;
}
- if (RegQueryValueExW(processor_key,
- L"~MHz",
- NULL,
- NULL,
- (BYTE*) &cpu_speed,
- &cpu_speed_size) != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegQueryValueExW(processor_key,
+ L"~MHz",
+ NULL,
+ NULL,
+ (BYTE*)&cpu_speed,
+ &cpu_speed_size);
+ if (err != ERROR_SUCCESS) {
RegCloseKey(processor_key);
goto error;
}
- if (RegQueryValueExW(processor_key,
- L"ProcessorNameString",
- NULL,
- NULL,
- (BYTE*) &cpu_brand,
- &cpu_brand_size) != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegQueryValueExW(processor_key,
+ L"ProcessorNameString",
+ NULL,
+ NULL,
+ (BYTE*)&cpu_brand,
+ &cpu_brand_size);
+ if (err != ERROR_SUCCESS) {
RegCloseKey(processor_key);
goto error;
}
@@ -1148,53 +1147,17 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
- wchar_t path[MAX_PATH];
- DWORD bufsize;
size_t len;
int r;
- if (buffer == NULL || size == NULL || *size == 0)
- return UV_EINVAL;
-
- /* Check if the USERPROFILE environment variable is set first */
- len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH);
+ /* Check if the USERPROFILE environment variable is set first. The task of
+ performing input validation on buffer and size is taken care of by
+ uv_os_getenv(). */
+ r = uv_os_getenv("USERPROFILE", buffer, size);
- if (len == 0) {
- r = GetLastError();
-
- /* Don't return an error if USERPROFILE was not found */
- if (r != ERROR_ENVVAR_NOT_FOUND)
- return uv_translate_sys_error(r);
- } else if (len > MAX_PATH) {
- /* This should not be possible */
- return UV_EIO;
- } else {
- /* Check how much space we need */
- bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
-
- if (bufsize == 0) {
- return uv_translate_sys_error(GetLastError());
- } else if (bufsize > *size) {
- *size = bufsize;
- return UV_ENOBUFS;
- }
-
- /* Convert to UTF-8 */
- bufsize = WideCharToMultiByte(CP_UTF8,
- 0,
- path,
- -1,
- buffer,
- *size,
- NULL,
- NULL);
-
- if (bufsize == 0)
- return uv_translate_sys_error(GetLastError());
-
- *size = bufsize - 1;
- return 0;
- }
+ /* Don't return an error if USERPROFILE was not found. */
+ if (r != UV_ENOENT)
+ return r;
/* USERPROFILE is not set, so call uv__getpwuid_r() */
r = uv__getpwuid_r(&pwd);
diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c
index 4ccdf0a5f..c33078614 100644
--- a/Utilities/cmlibuv/src/win/winapi.c
+++ b/Utilities/cmlibuv/src/win/winapi.c
@@ -55,12 +55,16 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
/* User32.dll function pointer */
sSetWinEventHook pSetWinEventHook;
+/* iphlpapi.dll function pointer */
+sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL;
+sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL;
void uv_winapi_init(void) {
HMODULE ntdll_module;
HMODULE kernel32_module;
HMODULE powrprof_module;
HMODULE user32_module;
+ HMODULE iphlpapi_module;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
@@ -166,4 +170,11 @@ void uv_winapi_init(void) {
GetProcAddress(user32_module, "SetWinEventHook");
}
+ iphlpapi_module = LoadLibraryA("iphlpapi.dll");
+ if (iphlpapi_module != NULL) {
+ pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid)
+ GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid");
+ pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW)
+ GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW");
+ }
}
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index 8993c6574..ae384b71a 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4784,4 +4784,19 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi
/* User32.dll function pointer */
extern sSetWinEventHook pSetWinEventHook;
+/* iphlpapi.dll function pointer */
+union _NET_LUID_LH;
+typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)(
+ ULONG InterfaceIndex,
+ union _NET_LUID_LH *InterfaceLuid);
+
+typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)(
+ const union _NET_LUID_LH *InterfaceLuid,
+ PWSTR InterfaceName,
+ size_t Length);
+
+extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid;
+extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW;
+
+
#endif /* UV_WIN_WINAPI_H_ */
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index 7cfa90f8a..84188954d 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -580,8 +580,10 @@ int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
memcpy(dest6, addr, sizeof(*dest6));
if (memcmp(&dest6->sin6_addr,
&uv_addr_ip6_any_.sin6_addr,
- sizeof(uv_addr_ip6_any_.sin6_addr)) == 0)
- dest6->sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
+ sizeof(uv_addr_ip6_any_.sin6_addr)) == 0) {
+ struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT;
+ dest6->sin6_addr = init_sin6_addr;
+ }
return 0;
default:
return UV_EINVAL;