summaryrefslogtreecommitdiff
path: root/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/IWYU/mapping.imp3
-rw-r--r--Utilities/Release/CMakeLogo.icobin24542 -> 17542 bytes
-rw-r--r--Utilities/Release/create-cmake-release.cmake2
-rw-r--r--Utilities/Release/linux64_release.cmake8
-rw-r--r--Utilities/Release/osx_release.cmake1
-rw-r--r--Utilities/Release/upload_release.cmake2
-rw-r--r--Utilities/Release/win32_release.cmake2
-rw-r--r--Utilities/Release/win64_release.cmake2
-rw-r--r--Utilities/Scripts/BoostScanDeps.cmake4
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rwxr-xr-xUtilities/Scripts/update-libarchive.bash2
-rwxr-xr-xUtilities/Scripts/update-liblzma.bash8
-rw-r--r--Utilities/Sphinx/cmake.py3
-rwxr-xr-xUtilities/Sphinx/create_identifiers.py1
-rw-r--r--Utilities/Sphinx/static/cmake-favicon.icobin1150 -> 1150 bytes
-rw-r--r--Utilities/Sphinx/static/cmake-logo-16.pngbin761 -> 893 bytes
-rw-r--r--Utilities/cmcurl/CMake/CMakeConfigurableFile.in1
-rw-r--r--Utilities/cmcurl/CMake/CurlSymbolHiding.cmake92
-rw-r--r--Utilities/cmcurl/CMake/CurlTests.c46
-rw-r--r--Utilities/cmcurl/CMake/FindCARES.cmake38
-rw-r--r--Utilities/cmcurl/CMake/FindGSS.cmake410
-rw-r--r--Utilities/cmcurl/CMake/FindLibSSH2.cmake14
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Macros.cmake62
-rw-r--r--Utilities/cmcurl/CMake/OtherTests.cmake61
-rw-r--r--Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake7
-rw-r--r--Utilities/cmcurl/CMake/Utilities.cmake41
-rw-r--r--Utilities/cmcurl/CMake/cmake_uninstall.cmake.in18
-rw-r--r--Utilities/cmcurl/CMake/curl-config.cmake59
-rw-r--r--Utilities/cmcurl/CMake/curl-config.cmake.in12
-rw-r--r--Utilities/cmcurl/CMakeLists.txt354
-rw-r--r--Utilities/cmcurl/curltest.c184
-rw-r--r--Utilities/cmcurl/include/curl/curl.h47
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h6
-rw-r--r--Utilities/cmcurl/include/curl/easy.h10
-rw-r--r--Utilities/cmcurl/include/curl/system.h22
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h8
-rw-r--r--Utilities/cmcurl/include/curl/urlapi.h120
-rw-r--r--Utilities/cmcurl/lib/CMakeLists.txt49
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc9
-rw-r--r--Utilities/cmcurl/lib/amigaos.h1
-rw-r--r--Utilities/cmcurl/lib/arpa_telnet.h6
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c37
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c14
-rw-r--r--Utilities/cmcurl/lib/base64.c3
-rw-r--r--Utilities/cmcurl/lib/conncache.c62
-rw-r--r--Utilities/cmcurl/lib/conncache.h4
-rw-r--r--Utilities/cmcurl/lib/connect.c12
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c40
-rw-r--r--Utilities/cmcurl/lib/cookie.c152
-rw-r--r--Utilities/cmcurl/lib/cookie.h4
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c3
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake15
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.c43
-rw-r--r--Utilities/cmcurl/lib/curl_ldap.h1
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c5
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c18
-rw-r--r--Utilities/cmcurl/lib/curl_path.c4
-rw-r--r--Utilities/cmcurl/lib/curl_path.h2
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.c4
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c3
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h20
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h1
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.c7
-rw-r--r--Utilities/cmcurl/lib/curl_threads.c13
-rw-r--r--Utilities/cmcurl/lib/curl_threads.h3
-rw-r--r--Utilities/cmcurl/lib/curlx.h1
-rw-r--r--Utilities/cmcurl/lib/dict.c12
-rw-r--r--Utilities/cmcurl/lib/doh.c920
-rw-r--r--Utilities/cmcurl/lib/doh.h105
-rw-r--r--Utilities/cmcurl/lib/dotdot.c2
-rw-r--r--Utilities/cmcurl/lib/dotdot.h2
-rw-r--r--Utilities/cmcurl/lib/easy.c57
-rw-r--r--Utilities/cmcurl/lib/easyif.h1
-rw-r--r--Utilities/cmcurl/lib/escape.c26
-rw-r--r--Utilities/cmcurl/lib/escape.h4
-rw-r--r--Utilities/cmcurl/lib/file.c45
-rw-r--r--Utilities/cmcurl/lib/file.h1
-rw-r--r--Utilities/cmcurl/lib/formdata.c16
-rw-r--r--Utilities/cmcurl/lib/ftp.c62
-rw-r--r--Utilities/cmcurl/lib/ftp.h2
-rw-r--r--Utilities/cmcurl/lib/getinfo.c23
-rw-r--r--Utilities/cmcurl/lib/gopher.c13
-rw-r--r--Utilities/cmcurl/lib/hash.c11
-rw-r--r--Utilities/cmcurl/lib/hmac.c4
-rw-r--r--Utilities/cmcurl/lib/hostasyn.c27
-rw-r--r--Utilities/cmcurl/lib/hostcheck.h1
-rw-r--r--Utilities/cmcurl/lib/hostip.c116
-rw-r--r--Utilities/cmcurl/lib/hostip.h13
-rw-r--r--Utilities/cmcurl/lib/hostip6.c35
-rw-r--r--Utilities/cmcurl/lib/http.c467
-rw-r--r--Utilities/cmcurl/lib/http.h19
-rw-r--r--Utilities/cmcurl/lib/http2.c334
-rw-r--r--Utilities/cmcurl/lib/http2.h5
-rw-r--r--Utilities/cmcurl/lib/http_chunks.h1
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c2
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c21
-rw-r--r--Utilities/cmcurl/lib/imap.c100
-rw-r--r--Utilities/cmcurl/lib/imap.h1
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.c2
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.h1
-rw-r--r--Utilities/cmcurl/lib/inet_pton.h1
-rw-r--r--Utilities/cmcurl/lib/krb5.c6
-rw-r--r--Utilities/cmcurl/lib/ldap.c27
-rw-r--r--Utilities/cmcurl/lib/llist.h1
-rw-r--r--Utilities/cmcurl/lib/md4.c2
-rw-r--r--Utilities/cmcurl/lib/md5.c42
-rw-r--r--Utilities/cmcurl/lib/memdebug.h9
-rw-r--r--Utilities/cmcurl/lib/mime.c53
-rw-r--r--Utilities/cmcurl/lib/multi.c282
-rw-r--r--Utilities/cmcurl/lib/multihandle.h8
-rw-r--r--Utilities/cmcurl/lib/netrc.c52
-rw-r--r--Utilities/cmcurl/lib/nonblock.c3
-rw-r--r--Utilities/cmcurl/lib/nonblock.h1
-rw-r--r--Utilities/cmcurl/lib/nwlib.c7
-rw-r--r--Utilities/cmcurl/lib/parsedate.h1
-rw-r--r--Utilities/cmcurl/lib/pingpong.c10
-rw-r--r--Utilities/cmcurl/lib/pipeline.c9
-rw-r--r--Utilities/cmcurl/lib/pop3.c9
-rw-r--r--Utilities/cmcurl/lib/progress.c39
-rw-r--r--Utilities/cmcurl/lib/progress.h14
-rw-r--r--Utilities/cmcurl/lib/psl.c111
-rw-r--r--Utilities/cmcurl/lib/psl.h47
-rw-r--r--Utilities/cmcurl/lib/rand.c6
-rw-r--r--Utilities/cmcurl/lib/rtsp.c33
-rw-r--r--Utilities/cmcurl/lib/rtsp.h1
-rw-r--r--Utilities/cmcurl/lib/security.c10
-rw-r--r--Utilities/cmcurl/lib/select.c8
-rw-r--r--Utilities/cmcurl/lib/select.h1
-rw-r--r--Utilities/cmcurl/lib/sendf.c48
-rw-r--r--Utilities/cmcurl/lib/sendf.h7
-rw-r--r--Utilities/cmcurl/lib/setopt.c74
-rw-r--r--Utilities/cmcurl/lib/sha256.c19
-rw-r--r--Utilities/cmcurl/lib/share.c11
-rw-r--r--Utilities/cmcurl/lib/share.h6
-rw-r--r--Utilities/cmcurl/lib/slist.c1
-rw-r--r--Utilities/cmcurl/lib/slist.h1
-rw-r--r--Utilities/cmcurl/lib/smb.c108
-rw-r--r--Utilities/cmcurl/lib/smb.h1
-rw-r--r--Utilities/cmcurl/lib/smtp.c10
-rw-r--r--Utilities/cmcurl/lib/sockaddr.h1
-rw-r--r--Utilities/cmcurl/lib/socks.c17
-rw-r--r--Utilities/cmcurl/lib/socks.h1
-rw-r--r--Utilities/cmcurl/lib/splay.c4
-rw-r--r--Utilities/cmcurl/lib/ssh-libssh.c64
-rw-r--r--Utilities/cmcurl/lib/ssh.c47
-rw-r--r--Utilities/cmcurl/lib/ssh.h4
-rw-r--r--Utilities/cmcurl/lib/strcase.h1
-rw-r--r--Utilities/cmcurl/lib/strdup.c2
-rw-r--r--Utilities/cmcurl/lib/strerror.c9
-rw-r--r--Utilities/cmcurl/lib/system_win32.c15
-rw-r--r--Utilities/cmcurl/lib/telnet.c59
-rw-r--r--Utilities/cmcurl/lib/telnet.h1
-rw-r--r--Utilities/cmcurl/lib/tftp.c31
-rw-r--r--Utilities/cmcurl/lib/tftp.h1
-rw-r--r--Utilities/cmcurl/lib/timeval.c23
-rw-r--r--Utilities/cmcurl/lib/transfer.c447
-rw-r--r--Utilities/cmcurl/lib/transfer.h5
-rw-r--r--Utilities/cmcurl/lib/url.c1295
-rw-r--r--Utilities/cmcurl/lib/url.h28
-rw-r--r--Utilities/cmcurl/lib/urlapi-int.h33
-rw-r--r--Utilities/cmcurl/lib/urlapi.c1340
-rw-r--r--Utilities/cmcurl/lib/urldata.h112
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/cram.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c16
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_gssapi.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_gssapi.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/version.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.c5
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.h1
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c508
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c37
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c91
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c3
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.c627
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.h32
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c28
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c195
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c3
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c310
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h34
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c26
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c18
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h6
-rw-r--r--Utilities/cmcurl/lib/warnless.h3
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c248
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt49
-rw-r--r--Utilities/cmlibarchive/build/cmake/config.h.in10
-rw-r--r--Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in1
-rw-r--r--Utilities/cmlibarchive/build/version2
-rw-r--r--Utilities/cmlibarchive/libarchive/CMakeLists.txt2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive.h8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_acl.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cmdline.c6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cryptor.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cryptor_private.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.h3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_match.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_pack_dev.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_platform.h6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd7.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd_private.h7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read.c12
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_append_filter.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c19
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_filter.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c292
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c21
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c29
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c109
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c30
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c32
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c32
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_util.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_version_details.c18
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_virtual.c11
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.32
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c335
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c12
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c19
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_filter.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c17
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c17
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c2
-rw-r--r--Utilities/cmliblzma/CMakeLists.txt18
-rw-r--r--Utilities/cmliblzma/COPYING2
-rw-r--r--Utilities/cmliblzma/common/common_w32res.rc2
-rw-r--r--Utilities/cmliblzma/common/sysdefs.h15
-rw-r--r--Utilities/cmliblzma/common/tuklib_integer.h35
-rw-r--r--Utilities/cmliblzma/config.h.in28
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma.h26
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/base.h88
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/block.h74
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/container.h222
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/filter.h13
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/hardware.h14
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/index.h34
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/index_hash.h4
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/lzma12.h (renamed from Utilities/cmliblzma/liblzma/api/lzma/lzma.h)2
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/version.h4
-rw-r--r--Utilities/cmliblzma/liblzma/check/check.c12
-rw-r--r--Utilities/cmliblzma/liblzma/check/check.h93
-rw-r--r--Utilities/cmliblzma/liblzma/check/crc32_fast.c8
-rw-r--r--Utilities/cmliblzma/liblzma/check/crc64_fast.c4
-rw-r--r--Utilities/cmliblzma/liblzma/check/sha256.c68
-rw-r--r--Utilities/cmliblzma/liblzma/common/alone_decoder.c73
-rw-r--r--Utilities/cmliblzma/liblzma/common/alone_decoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/alone_encoder.c68
-rw-r--r--Utilities/cmliblzma/liblzma/common/auto_decoder.c51
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c10
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c134
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_buffer_encoder.h24
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_decoder.c67
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_decoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_encoder.c52
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_encoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_header_decoder.c37
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_header_encoder.c19
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_util.c13
-rw-r--r--Utilities/cmliblzma/liblzma/common/common.c103
-rw-r--r--Utilities/cmliblzma/liblzma/common/common.h138
-rw-r--r--Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c4
-rw-r--r--Utilities/cmliblzma/liblzma/common/easy_encoder.c1
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c15
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c18
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_common.c129
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_common.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_decoder.c87
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_decoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_encoder.c163
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_encoder.h6
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c3
-rw-r--r--Utilities/cmliblzma/liblzma/common/hardware_cputhreads.c (renamed from Utilities/cmliblzma/liblzma/common/stream_encoder.h)17
-rw-r--r--Utilities/cmliblzma/liblzma/common/index.c166
-rw-r--r--Utilities/cmliblzma/liblzma/common/index_decoder.c63
-rw-r--r--Utilities/cmliblzma/liblzma/common/index_encoder.c35
-rw-r--r--Utilities/cmliblzma/liblzma/common/index_encoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/index_hash.c16
-rw-r--r--Utilities/cmliblzma/liblzma/common/memcmplen.h175
-rw-r--r--Utilities/cmliblzma/liblzma/common/outqueue.c184
-rw-r--r--Utilities/cmliblzma/liblzma/common/outqueue.h156
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c25
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_decoder.c102
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_decoder.h5
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_encoder.c108
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c1143
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/vli_decoder.c4
-rw-r--r--Utilities/cmliblzma/liblzma/common/vli_encoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/common/vli_size.c3
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_common.c31
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_decoder.c29
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_decoder.h5
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_encoder.c31
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_encoder.h3
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_private.h6
-rw-r--r--Utilities/cmliblzma/liblzma/liblzma.pc.in2
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_decoder.c97
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_decoder.h52
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_encoder.c224
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_encoder.h21
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h21
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c230
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/fastpos.h57
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c49
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.h5
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.c85
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.h4
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_common.h54
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c253
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_decoder.h7
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c150
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder.h16
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c49
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c340
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder_presets.c8
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h28
-rw-r--r--Utilities/cmliblzma/liblzma/rangecoder/range_common.h7
-rw-r--r--Utilities/cmliblzma/liblzma/rangecoder/range_decoder.h16
-rw-r--r--Utilities/cmliblzma/liblzma/rangecoder/range_encoder.h3
-rw-r--r--Utilities/cmliblzma/liblzma/simple/arm.c12
-rw-r--r--Utilities/cmliblzma/liblzma/simple/armthumb.c12
-rw-r--r--Utilities/cmliblzma/liblzma/simple/ia64.c32
-rw-r--r--Utilities/cmliblzma/liblzma/simple/powerpc.c10
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_coder.c91
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_coder.h36
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_decoder.c7
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_decoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_private.h15
-rw-r--r--Utilities/cmliblzma/liblzma/simple/sparc.c13
-rw-r--r--Utilities/cmliblzma/liblzma/simple/x86.c42
-rw-r--r--Utilities/cmlibrhash/librhash/rhash.c2
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt16
357 files changed, 12787 insertions, 6305 deletions
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index 892cdcb1e..5af8b85dd 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -52,6 +52,9 @@
#{ symbol: [ "std::pair", private, "<map>", public ] },
#{ symbol: [ "std::pair", private, "<set>", public ] },
+ # HACK: iwyu wrongly thinks that <system_error> is needed for std::hash
+ { symbol: [ "std::hash", private, "<functional>", public ] },
+
# __decay_and_strip is used internally in the C++11 standard library.
# IWYU does not classify it as internal and suggests to add <type_traits>.
# To ignore it, we simply map it to a file that is included anyway.
diff --git a/Utilities/Release/CMakeLogo.ico b/Utilities/Release/CMakeLogo.ico
index e13bb156f..c1006122b 100644
--- a/Utilities/Release/CMakeLogo.ico
+++ b/Utilities/Release/CMakeLogo.ico
Binary files differ
diff --git a/Utilities/Release/create-cmake-release.cmake b/Utilities/Release/create-cmake-release.cmake
index 3af1b035f..b3cc35232 100644
--- a/Utilities/Release/create-cmake-release.cmake
+++ b/Utilities/Release/create-cmake-release.cmake
@@ -54,7 +54,7 @@ cd \${name}-build &&
-DCMAKE_INSTALL_PREFIX=\"\$inst/\" \\
-DCMAKE_DOC_DIR=doc/cmake \\
-DSPHINX_EXECUTABLE=\"${SPHINX_EXECUTABLE}\" \\
- -DSPHINX_HTML=ON -DSPHINX_MAN=ON &&
+ -DSPHINX_HTML=ON -DSPHINX_MAN=ON -DSPHINX_QTHELP=ON &&
make install &&
cd .. &&
tar czf \${name}.tar.gz \${name} ||
diff --git a/Utilities/Release/linux64_release.cmake b/Utilities/Release/linux64_release.cmake
index 04a74ac80..dc3412020 100644
--- a/Utilities/Release/linux64_release.cmake
+++ b/Utilities/Release/linux64_release.cmake
@@ -3,8 +3,8 @@ set(BOOTSTRAP_ARGS "--docdir=doc/cmake")
set(HOST linux64)
set(MAKE_PROGRAM "make")
set(CPACK_BINARY_GENERATORS "STGZ TGZ")
-set(CC /opt/gcc-6.1.0/bin/gcc)
-set(CXX /opt/gcc-6.1.0/bin/g++)
+set(CC /opt/gcc-8.2.0/bin/gcc)
+set(CXX /opt/gcc-8.2.0/bin/g++)
set(CFLAGS "")
set(CXXFLAGS "")
set(qt_prefix "/home/kitware/qt-5.7.0")
@@ -34,12 +34,16 @@ 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_CursesDialog:BOOL=ON
BUILD_QtDialog:BOOL=TRUE
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMAKE_PREFIX_PATH:STRING=${qt_prefix}
CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES:STRING=${qt_xcb_libs}
")
+set(ENV [[
+export CMAKE_PREFIX_PATH=/opt/binutils-2.31
+]])
# Exclude Qt5 tests because our Qt5 is static.
set(EXTRA_CTEST_ARGS "-E Qt5")
diff --git a/Utilities/Release/osx_release.cmake b/Utilities/Release/osx_release.cmake
index c69eb1187..be11d470b 100644
--- a/Utilities/Release/osx_release.cmake
+++ b/Utilities/Release/osx_release.cmake
@@ -19,6 +19,7 @@ CMAKE_OSX_ARCHITECTURES:STRING=x86_64
CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.7
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CPACK_SYSTEM_NAME:STRING=Darwin-x86_64
+BUILD_CursesDialog:BOOL=ON
BUILD_QtDialog:BOOL=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMake_INSTALL_DEPENDENCIES:BOOL=ON
diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake
index 1edcd65b1..bbc74379d 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.12)
+ set(VERSION 3.13)
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 f9e35a543..2e817d925 100644
--- a/Utilities/Release/win32_release.cmake
+++ b/Utilities/Release/win32_release.cmake
@@ -39,6 +39,6 @@ get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(GIT_EXTRA "git config core.autocrlf true")
if(CMAKE_CREATE_VERSION STREQUAL "nightly")
# Some tests fail spuriously too often.
- set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf'")
+ set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf|Module.ExternalData'")
endif()
include(${path}/release_cmake.cmake)
diff --git a/Utilities/Release/win64_release.cmake b/Utilities/Release/win64_release.cmake
index 02e409652..33af830c4 100644
--- a/Utilities/Release/win64_release.cmake
+++ b/Utilities/Release/win64_release.cmake
@@ -39,6 +39,6 @@ get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(GIT_EXTRA "git config core.autocrlf true")
if(CMAKE_CREATE_VERSION STREQUAL "nightly")
# Some tests fail spuriously too often.
- set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf'")
+ set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf|Module.ExternalData'")
endif()
include(${path}/release_cmake.cmake)
diff --git a/Utilities/Scripts/BoostScanDeps.cmake b/Utilities/Scripts/BoostScanDeps.cmake
index bd2e6a879..28a94ce89 100644
--- a/Utilities/Scripts/BoostScanDeps.cmake
+++ b/Utilities/Scripts/BoostScanDeps.cmake
@@ -51,12 +51,12 @@ function(_Boost_FIND_COMPONENT_DEPENDENCIES component includedir _ret_libs)
# Special-case since it is part of mpi; look only in boost/mpi/python*
if(component STREQUAL "mpi_python")
- set(_boost_DEPS "python")
+ set(_boost_DEPS "python\${component_python_version}")
set(library_component TRUE)
set(_boost_unprocessed_headers ${_boost_mpi_python_headers})
# Special-case since it is part of python; look only in boost/python/numpy*
elseif(component STREQUAL "numpy")
- set(_boost_DEPS "python")
+ set(_boost_DEPS "python\${component_python_version}")
set(library_component TRUE)
set(_boost_unprocessed_headers ${_boost_python_numpy_headers})
# Special-case since it is a serialization variant; look in boost/serialization
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index b02180f09..fb46052e8 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_60_0"
+readonly tag="curl-7_62_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash
index 7534f9447..31886584f 100755
--- a/Utilities/Scripts/update-libarchive.bash
+++ b/Utilities/Scripts/update-libarchive.bash
@@ -8,7 +8,7 @@ readonly name="LibArchive"
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
readonly subtree="Utilities/cmlibarchive"
readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.3.2"
+readonly tag="v3.3.3"
readonly shortlog=false
readonly paths="
CMakeLists.txt
diff --git a/Utilities/Scripts/update-liblzma.bash b/Utilities/Scripts/update-liblzma.bash
index 088eb91e0..fdf66b3ec 100755
--- a/Utilities/Scripts/update-liblzma.bash
+++ b/Utilities/Scripts/update-liblzma.bash
@@ -7,8 +7,8 @@ shopt -s dotglob
readonly name="liblzma"
readonly ownership="liblzma upstream <xz-devel@tukaani.org>"
readonly subtree="Utilities/cmliblzma"
-readonly repo="http://git.tukaani.org/xz.git"
-readonly tag="v5.0.8"
+readonly repo="https://git.tukaani.org/xz.git"
+readonly tag="v5.2.4"
readonly shortlog=false
readonly paths="
COPYING
@@ -24,6 +24,10 @@ extract_source () {
mv src/common .
mv src/liblzma .
rmdir src
+ rm liblzma/Makefile.*
+ rm liblzma/*/Makefile.*
+ rm liblzma/liblzma.map
+ rm liblzma/validate_map.sh
popd
}
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index b0c8f7186..ebf44da45 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'),
+ 'cpack_gen': _cmake_index_entry('cpack generator'),
'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
'manual': _cmake_index_entry('manual'),
@@ -325,6 +326,7 @@ class CMakeDomain(Domain):
label = 'CMake'
object_types = {
'command': ObjType('command', 'command'),
+ 'cpack_gen': ObjType('cpack_gen', 'cpack_gen'),
'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
'variable': ObjType('variable', 'variable'),
@@ -358,6 +360,7 @@ class CMakeDomain(Domain):
}
roles = {
'command': CMakeXRefRole(fix_parens = True, lowercase = True),
+ 'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
'variable': CMakeXRefRole(),
diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py
index e63895004..6716b480d 100755
--- a/Utilities/Sphinx/create_identifiers.py
+++ b/Utilities/Sphinx/create_identifiers.py
@@ -21,6 +21,7 @@ newlines = []
for line in lines:
mapping = (("command", "command"),
+ ("cpack generator", "cpack_gen"),
("envvar", "envvar"),
("variable", "variable"),
("generator", "generator"),
diff --git a/Utilities/Sphinx/static/cmake-favicon.ico b/Utilities/Sphinx/static/cmake-favicon.ico
index fce8f922f..ae529f54e 100644
--- a/Utilities/Sphinx/static/cmake-favicon.ico
+++ b/Utilities/Sphinx/static/cmake-favicon.ico
Binary files differ
diff --git a/Utilities/Sphinx/static/cmake-logo-16.png b/Utilities/Sphinx/static/cmake-logo-16.png
index 2039c25b0..9c95b75f3 100644
--- a/Utilities/Sphinx/static/cmake-logo-16.png
+++ b/Utilities/Sphinx/static/cmake-logo-16.png
Binary files differ
diff --git a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
index 4cf74a12b..df2c382e9 100644
--- a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
+++ b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
@@ -1,2 +1 @@
@CMAKE_CONFIGURABLE_FILE_CONTENT@
-
diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
index 9f7d29633..15ba46e46 100644
--- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
+++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
@@ -4,57 +4,57 @@ option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide al
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS)
- set(SUPPORTS_SYMBOL_HIDING FALSE)
+ set(SUPPORTS_SYMBOL_HIDING FALSE)
- if(CMAKE_C_COMPILER_ID MATCHES "Clang")
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
- set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
- elseif(CMAKE_COMPILER_IS_GNUCC)
- if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
- set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
- else()
- execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
- OUTPUT_VARIABLE GCC_VERSION)
- endif()
- if(NOT GCC_VERSION VERSION_LESS 3.4)
- # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
- set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
- endif()
- elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__global")
- set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
- elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
- # note: this should probably just check for version 9.1.045 but I'm not 100% sure
- # so let's to it the same way autotools do.
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
- set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
- check_c_source_compiles("#include <stdio.h>
- int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
- if(NOT _no_bug)
- set(SUPPORTS_SYMBOL_HIDING FALSE)
- set(_SYMBOL_EXTERN "")
- set(_CFLAG_SYMBOLS_HIDE "")
- endif()
- elseif(MSVC)
- set(SUPPORTS_SYMBOL_HIDING TRUE)
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ elseif(CMAKE_COMPILER_IS_GNUCC)
+ if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
+ set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
+ else()
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+ endif()
+ if(NOT GCC_VERSION VERSION_LESS 3.4)
+ # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
endif()
+ elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__global")
+ set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
+ # note: this should probably just check for version 9.1.045 but I'm not 100% sure
+ # so let's to it the same way autotools do.
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ check_c_source_compiles("#include <stdio.h>
+ int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
+ if(NOT _no_bug)
+ set(SUPPORTS_SYMBOL_HIDING FALSE)
+ set(_SYMBOL_EXTERN "")
+ set(_CFLAG_SYMBOLS_HIDE "")
+ endif()
+ elseif(MSVC)
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ endif()
- set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
+ set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
elseif(MSVC)
- if(NOT CMAKE_VERSION VERSION_LESS 3.7)
- set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
- set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
- else()
- message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
- set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
- endif()
-elseif()
+ if(NOT CMAKE_VERSION VERSION_LESS 3.7)
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
+ else()
+ message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
+ set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
+ endif()
+elseif()
+ set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
endif()
set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index bc36c8ef7..9388c835b 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -507,30 +507,30 @@ main ()
#ifdef HAVE_GLIBC_STRERROR_R
#include <string.h>
#include <errno.h>
+
+void check(char c) {}
+
int
main () {
- char buffer[1024]; /* big enough to play with */
- char *string =
- strerror_r(EACCES, buffer, sizeof(buffer));
- /* this should've returned a string */
- if(!string || !string[0])
- return 99;
- return 0;
+ char buffer[1024];
+ /* This will not compile if strerror_r does not return a char* */
+ check(strerror_r(EACCES, buffer, sizeof(buffer))[0]);
+ return 0;
}
#endif
#ifdef HAVE_POSIX_STRERROR_R
#include <string.h>
#include <errno.h>
+
+/* float, because a pointer can't be implicitly cast to float */
+void check(float f) {}
+
int
main () {
- char buffer[1024]; /* big enough to play with */
- int error =
- strerror_r(EACCES, buffer, sizeof(buffer));
- /* This should've returned zero, and written an error string in the
- buffer.*/
- if(!buffer[0] || error)
- return 99;
- return 0;
+ char buffer[1024];
+ /* This will not compile if strerror_r does not return an int */
+ check(strerror_r(EACCES, buffer, sizeof(buffer)));
+ return 0;
}
#endif
#ifdef HAVE_FSETXATTR_6
@@ -549,3 +549,19 @@ main() {
return 0;
}
#endif
+#ifdef HAVE_CLOCK_GETTIME_MONOTONIC
+#include <time.h>
+int
+main() {
+ struct timespec ts = {0, 0};
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return 0;
+}
+#endif
+#ifdef HAVE_BUILTIN_AVAILABLE
+int
+main() {
+ if(__builtin_available(macOS 10.12, *)) {}
+ return 0;
+}
+#endif
diff --git a/Utilities/cmcurl/CMake/FindCARES.cmake b/Utilities/cmcurl/CMake/FindCARES.cmake
index c4ab5f132..723044a64 100644
--- a/Utilities/cmcurl/CMake/FindCARES.cmake
+++ b/Utilities/cmcurl/CMake/FindCARES.cmake
@@ -7,36 +7,36 @@
# also defined, but not for general use are
# CARES_LIBRARY, where to find the c-ares library.
-FIND_PATH(CARES_INCLUDE_DIR ares.h
+find_path(CARES_INCLUDE_DIR ares.h
/usr/local/include
/usr/include
)
-SET(CARES_NAMES ${CARES_NAMES} cares)
-FIND_LIBRARY(CARES_LIBRARY
+set(CARES_NAMES ${CARES_NAMES} cares)
+find_library(CARES_LIBRARY
NAMES ${CARES_NAMES}
PATHS /usr/lib /usr/local/lib
)
-IF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
- SET(CARES_LIBRARIES ${CARES_LIBRARY})
- SET(CARES_FOUND "YES")
-ELSE (CARES_LIBRARY AND CARES_INCLUDE_DIR)
- SET(CARES_FOUND "NO")
-ENDIF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
+if(CARES_LIBRARY AND CARES_INCLUDE_DIR)
+ set(CARES_LIBRARIES ${CARES_LIBRARY})
+ set(CARES_FOUND "YES")
+else()
+ set(CARES_FOUND "NO")
+endif()
-IF (CARES_FOUND)
- IF (NOT CARES_FIND_QUIETLY)
- MESSAGE(STATUS "Found c-ares: ${CARES_LIBRARIES}")
- ENDIF (NOT CARES_FIND_QUIETLY)
-ELSE (CARES_FOUND)
- IF (CARES_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find c-ares library")
- ENDIF (CARES_FIND_REQUIRED)
-ENDIF (CARES_FOUND)
+if(CARES_FOUND)
+ if(NOT CARES_FIND_QUIETLY)
+ message(STATUS "Found c-ares: ${CARES_LIBRARIES}")
+ endif()
+else()
+ if(CARES_FIND_REQUIRED)
+ message(FATAL_ERROR "Could not find c-ares library")
+ endif()
+endif()
-MARK_AS_ADVANCED(
+mark_as_advanced(
CARES_LIBRARY
CARES_INCLUDE_DIR
)
diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake
index 60dcb73c9..7a637fc29 100644
--- a/Utilities/cmcurl/CMake/FindGSS.cmake
+++ b/Utilities/cmcurl/CMake/FindGSS.cmake
@@ -28,211 +28,209 @@ set(_GSS_ROOT_HINTS
# try to find library using system pkg-config if user didn't specify root dir
if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
- if(UNIX)
- find_package(PkgConfig QUIET)
- pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
- list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
- elseif(WIN32)
- list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
- endif()
+ if(UNIX)
+ find_package(PkgConfig QUIET)
+ pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
+ list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
+ elseif(WIN32)
+ list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
+ endif()
endif()
if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach.
- find_file(_GSS_CONFIGURE_SCRIPT
- NAMES
- "krb5-config"
- HINTS
- ${_GSS_ROOT_HINTS}
- PATH_SUFFIXES
- bin
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
+ find_file(_GSS_CONFIGURE_SCRIPT
+ NAMES
+ "krb5-config"
+ HINTS
+ ${_GSS_ROOT_HINTS}
+ PATH_SUFFIXES
+ bin
+ NO_CMAKE_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ )
+
+ # if not found in user-supplied directories, maybe system knows better
+ find_file(_GSS_CONFIGURE_SCRIPT
+ NAMES
+ "krb5-config"
+ PATH_SUFFIXES
+ bin
+ )
+
+ if(_GSS_CONFIGURE_SCRIPT)
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
+ OUTPUT_VARIABLE _GSS_CFLAGS
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+ )
+ message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
+ if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+ # should also work in an odd case when multiple directories are given
+ string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
+ string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
+ string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
+
+ foreach(_flag ${_GSS_CFLAGS})
+ if(_flag MATCHES "^-I.*")
+ string(REGEX REPLACE "^-I" "" _val "${_flag}")
+ list(APPEND _GSS_INCLUDE_DIR "${_val}")
+ else()
+ list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
+ endif()
+ endforeach()
+ endif()
+
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
+ OUTPUT_VARIABLE _GSS_LIB_FLAGS
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
+ message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
+
+ if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+ # this script gives us libraries and link directories. Blah. We have to deal with it.
+ string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
+ string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+ string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+
+ foreach(_flag ${_GSS_LIB_FLAGS})
+ if(_flag MATCHES "^-l.*")
+ string(REGEX REPLACE "^-l" "" _val "${_flag}")
+ list(APPEND _GSS_LIBRARIES "${_val}")
+ elseif(_flag MATCHES "^-L.*")
+ string(REGEX REPLACE "^-L" "" _val "${_flag}")
+ list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
+ else()
+ list(APPEND _GSS_LINKER_FLAGS "${_flag}")
+ endif()
+ endforeach()
+ endif()
- # if not found in user-supplied directories, maybe system knows better
- find_file(_GSS_CONFIGURE_SCRIPT
- NAMES
- "krb5-config"
- PATH_SUFFIXES
- bin
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
+ OUTPUT_VARIABLE _GSS_VERSION
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
- if(_GSS_CONFIGURE_SCRIPT)
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
- OUTPUT_VARIABLE _GSS_CFLAGS
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
-message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
- if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
- # should also work in an odd case when multiple directories are given
- string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
- string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
- string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
-
- foreach(_flag ${_GSS_CFLAGS})
- if(_flag MATCHES "^-I.*")
- string(REGEX REPLACE "^-I" "" _val "${_flag}")
- list(APPEND _GSS_INCLUDE_DIR "${_val}")
- else()
- list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
- endif()
- endforeach()
- endif()
+ # older versions may not have the "--version" parameter. In this case we just don't care.
+ if(_GSS_CONFIGURE_FAILED)
+ set(_GSS_VERSION 0)
+ endif()
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
- OUTPUT_VARIABLE _GSS_LIB_FLAGS
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
-message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
- if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
- # this script gives us libraries and link directories. Blah. We have to deal with it.
- string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
- string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
- string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
-
- foreach(_flag ${_GSS_LIB_FLAGS})
- if(_flag MATCHES "^-l.*")
- string(REGEX REPLACE "^-l" "" _val "${_flag}")
- list(APPEND _GSS_LIBRARIES "${_val}")
- elseif(_flag MATCHES "^-L.*")
- string(REGEX REPLACE "^-L" "" _val "${_flag}")
- list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
- else()
- list(APPEND _GSS_LINKER_FLAGS "${_flag}")
- endif()
- endforeach()
- endif()
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
+ OUTPUT_VARIABLE _GSS_VENDOR
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+ )
+ # older versions may not have the "--vendor" parameter. In this case we just don't care.
+ if(_GSS_CONFIGURE_FAILED)
+ set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+ else()
+ if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
+ set(GSS_FLAVOUR "Heimdal")
+ else()
+ set(GSS_FLAVOUR "MIT")
+ endif()
+ endif()
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
- OUTPUT_VARIABLE _GSS_VERSION
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
+ else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
- # older versions may not have the "--version" parameter. In this case we just don't care.
- if(_GSS_CONFIGURE_FAILED)
- set(_GSS_VERSION 0)
- endif()
+ find_path(_GSS_INCLUDE_DIR
+ NAMES
+ "gssapi/gssapi.h"
+ HINTS
+ ${_GSS_ROOT_HINTS}
+ PATH_SUFFIXES
+ include
+ inc
+ )
+ if(_GSS_INCLUDE_DIR) #jay, we've found something
+ set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
+ check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
- OUTPUT_VARIABLE _GSS_VENDOR
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
+ if(_GSS_HAVE_MIT_HEADERS)
+ set(GSS_FLAVOUR "MIT")
+ else()
+ # prevent compiling the header - just check if we can include it
+ set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
+ check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
+
+ check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
+ if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
+ set(GSS_FLAVOUR "Heimdal")
+ endif()
+ set(CMAKE_REQUIRED_DEFINITIONS "")
+ endif()
+ else()
+ # I'm not convienced if this is the right way but this is what autotools do at the moment
+ find_path(_GSS_INCLUDE_DIR
+ NAMES
+ "gssapi.h"
+ HINTS
+ ${_GSS_ROOT_HINTS}
+ PATH_SUFFIXES
+ include
+ inc
+ )
+
+ if(_GSS_INCLUDE_DIR)
+ set(GSS_FLAVOUR "Heimdal")
+ endif()
+ endif()
+
+ # if we have headers, check if we can link libraries
+ if(GSS_FLAVOUR)
+ set(_GSS_LIBDIR_SUFFIXES "")
+ set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
+ get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
+ list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
- # older versions may not have the "--vendor" parameter. In this case we just don't care.
- if(_GSS_CONFIGURE_FAILED)
- set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+ if(WIN32)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
+ if(GSS_FLAVOUR STREQUAL "MIT")
+ set(_GSS_LIBNAME "gssapi64")
+ else()
+ set(_GSS_LIBNAME "libgssapi")
+ endif()
else()
- if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
- set(GSS_FLAVOUR "Heimdal")
- else()
- set(GSS_FLAVOUR "MIT")
- endif()
+ list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
+ if(GSS_FLAVOUR STREQUAL "MIT")
+ set(_GSS_LIBNAME "gssapi32")
+ else()
+ set(_GSS_LIBNAME "libgssapi")
+ endif()
endif()
-
- else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
-
- find_path(_GSS_INCLUDE_DIR
- NAMES
- "gssapi/gssapi.h"
- HINTS
- ${_GSS_ROOT_HINTS}
- PATH_SUFFIXES
- include
- inc
- )
-
- if(_GSS_INCLUDE_DIR) #jay, we've found something
- set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
- check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
-
- if(_GSS_HAVE_MIT_HEADERS)
- set(GSS_FLAVOUR "MIT")
- else()
- # prevent compiling the header - just check if we can include it
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
- check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
-
- check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
- if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
- set(GSS_FLAVOUR "Heimdal")
- endif()
- set(CMAKE_REQUIRED_DEFINITIONS "")
- endif()
+ else()
+ list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
+ if(GSS_FLAVOUR STREQUAL "MIT")
+ set(_GSS_LIBNAME "gssapi_krb5")
else()
- # I'm not convienced if this is the right way but this is what autotools do at the moment
- find_path(_GSS_INCLUDE_DIR
- NAMES
- "gssapi.h"
- HINTS
- ${_GSS_ROOT_HINTS}
- PATH_SUFFIXES
- include
- inc
- )
-
- if(_GSS_INCLUDE_DIR)
- set(GSS_FLAVOUR "Heimdal")
- endif()
+ set(_GSS_LIBNAME "gssapi")
endif()
+ endif()
- # if we have headers, check if we can link libraries
- if(GSS_FLAVOUR)
- set(_GSS_LIBDIR_SUFFIXES "")
- set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
- get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
- list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
-
- if(WIN32)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
- if(GSS_FLAVOUR STREQUAL "MIT")
- set(_GSS_LIBNAME "gssapi64")
- else()
- set(_GSS_LIBNAME "libgssapi")
- endif()
- else()
- list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
- if(GSS_FLAVOUR STREQUAL "MIT")
- set(_GSS_LIBNAME "gssapi32")
- else()
- set(_GSS_LIBNAME "libgssapi")
- endif()
- endif()
- else()
- list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
- if(GSS_FLAVOUR STREQUAL "MIT")
- set(_GSS_LIBNAME "gssapi_krb5")
- else()
- set(_GSS_LIBNAME "gssapi")
- endif()
- endif()
-
- find_library(_GSS_LIBRARIES
- NAMES
- ${_GSS_LIBNAME}
- HINTS
- ${_GSS_LIBDIR_HINTS}
- PATH_SUFFIXES
- ${_GSS_LIBDIR_SUFFIXES}
- )
-
- endif()
+ find_library(_GSS_LIBRARIES
+ NAMES
+ ${_GSS_LIBNAME}
+ HINTS
+ ${_GSS_LIBDIR_HINTS}
+ PATH_SUFFIXES
+ ${_GSS_LIBDIR_SUFFIXES}
+ )
endif()
+ endif()
else()
- if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
- set(GSS_FLAVOUR "MIT")
- set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
- else()
- set(GSS_FLAVOUR "Heimdal")
- set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
- endif()
+ if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
+ set(GSS_FLAVOUR "MIT")
+ set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
+ else()
+ set(GSS_FLAVOUR "Heimdal")
+ set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
+ endif()
endif()
set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR})
@@ -243,36 +241,34 @@ set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS})
set(GSS_VERSION ${_GSS_VERSION})
if(GSS_FLAVOUR)
+ if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
+ else()
+ set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
+ endif()
- if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
- else()
- set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
- endif()
-
- if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
- file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
- REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
+ if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
+ file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
+ REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
- string(REGEX MATCH "[0-9]\\.[^\"]+"
- GSS_VERSION "${heimdal_version_str}")
- endif()
+ string(REGEX MATCH "[0-9]\\.[^\"]+"
+ GSS_VERSION "${heimdal_version_str}")
+ endif()
- if(NOT GSS_VERSION)
- set(GSS_VERSION "Heimdal Unknown")
- endif()
- elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
- get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
- if(WIN32 AND _MIT_VERSION)
- set(GSS_VERSION "${_MIT_VERSION}")
- else()
- set(GSS_VERSION "MIT Unknown")
- endif()
+ if(NOT GSS_VERSION)
+ set(GSS_VERSION "Heimdal Unknown")
endif()
+ elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
+ get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
+ if(WIN32 AND _MIT_VERSION)
+ set(GSS_VERSION "${_MIT_VERSION}")
+ else()
+ set(GSS_VERSION "MIT Unknown")
+ endif()
+ endif()
endif()
-
include(FindPackageHandleStandardArgs)
set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
diff --git a/Utilities/cmcurl/CMake/FindLibSSH2.cmake b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
index 12a7c612b..84822dba7 100644
--- a/Utilities/cmcurl/CMake/FindLibSSH2.cmake
+++ b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
@@ -5,14 +5,14 @@
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
# LIBSSH2_LIBRARY - the libssh2 library name
-if (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
+if(LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
set(LibSSH2_FIND_QUIETLY TRUE)
-endif (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
+endif()
-FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h
+find_path(LIBSSH2_INCLUDE_DIR libssh2.h
)
-FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2
+find_library(LIBSSH2_LIBRARY NAMES ssh2
)
if(LIBSSH2_INCLUDE_DIR)
@@ -27,9 +27,9 @@ if(LIBSSH2_INCLUDE_DIR)
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}")
set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}")
-endif(LIBSSH2_INCLUDE_DIR)
+endif()
include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
+find_package_handle_standard_args(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
-MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
+mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
index 4e566cf02..348b9612d 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
@@ -14,5 +14,5 @@ find_package_handle_standard_args(NGHTTP2
"Could NOT find NGHTTP2"
)
-set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR} )
+set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
diff --git a/Utilities/cmcurl/CMake/Macros.cmake b/Utilities/cmcurl/CMake/Macros.cmake
index 82aadca9d..7f7134515 100644
--- a/Utilities/cmcurl/CMake/Macros.cmake
+++ b/Utilities/cmcurl/CMake/Macros.cmake
@@ -5,35 +5,35 @@
# multiple times with a sequence of possibly dependent libraries in
# order of least-to-most-dependent. Some libraries depend on others
# to link correctly.
-macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
+macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE)
check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
${VARIABLE})
if(${VARIABLE})
set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
- endif(${VARIABLE})
-endmacro(CHECK_LIBRARY_EXISTS_CONCAT)
+ endif()
+endmacro()
# Check if header file exists and add it to the list.
# This macro is intended to be called multiple times with a sequence of
# possibly dependent header files. Some headers depend on others to be
# compiled correctly.
-macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
+macro(check_include_file_concat FILE VARIABLE)
check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE})
if(${VARIABLE})
set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
- endif(${VARIABLE})
-endmacro(CHECK_INCLUDE_FILE_CONCAT)
+ endif()
+endmacro()
# For other curl specific tests, use this macro.
-macro(CURL_INTERNAL_TEST CURL_TEST)
+macro(curl_internal_test CURL_TEST)
if(NOT DEFINED "${CURL_TEST}")
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LIBRARIES)
set(CURL_TEST_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
- endif(CMAKE_REQUIRED_LIBRARIES)
+ endif()
message(STATUS "Performing Curl Test ${CURL_TEST}")
try_compile(${CURL_TEST}
@@ -48,53 +48,17 @@ macro(CURL_INTERNAL_TEST CURL_TEST)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing Curl Test ${CURL_TEST} passed with the following output:\n"
"${OUTPUT}\n")
- else(${CURL_TEST})
+ else()
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}\n")
- endif(${CURL_TEST})
- endif()
-endmacro(CURL_INTERNAL_TEST)
-
-macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
- if(NOT DEFINED "${CURL_TEST}_COMPILE")
- set(MACRO_CHECK_FUNCTION_DEFINITIONS
- "-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
- if(CMAKE_REQUIRED_LIBRARIES)
- set(CURL_TEST_ADD_LIBRARIES
- "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
- endif(CMAKE_REQUIRED_LIBRARIES)
-
- message(STATUS "Performing Curl Test ${CURL_TEST}")
- try_run(${CURL_TEST} ${CURL_TEST}_COMPILE
- ${CMAKE_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
- CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
- "${CURL_TEST_ADD_LIBRARIES}"
- OUTPUT_VARIABLE OUTPUT)
- if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
- set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
- message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
- else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
- message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
- set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
- file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
- "Performing Curl Test ${CURL_TEST} failed with the following output:\n"
- "${OUTPUT}")
- if(${CURL_TEST}_COMPILE)
- file(APPEND
- "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
- "There was a problem running this test\n")
- endif(${CURL_TEST}_COMPILE)
- file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
- "\n\n")
- endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
+ endif()
endif()
-endmacro(CURL_INTERNAL_TEST_RUN)
+endmacro()
-macro(CURL_NROFF_CHECK)
+macro(curl_nroff_check)
find_program(NROFF NAMES gnroff nroff)
if(NROFF)
# Need a way to write to stdin, this will do
@@ -121,4 +85,4 @@ macro(CURL_NROFF_CHECK)
else()
message(WARNING "Found no *nroff program")
endif()
-endmacro(CURL_NROFF_CHECK)
+endmacro()
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index 989f04eb2..ce6d3e13a 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -5,8 +5,8 @@ set(_source_epilogue "#undef inline")
macro(add_header_include check header)
if(${check})
set(_source_epilogue "${_source_epilogue}\n#include <${header}>")
- endif(${check})
-endmacro(add_header_include)
+ endif()
+endmacro()
set(signature_call_conv)
if(HAVE_WINDOWS_H)
@@ -19,10 +19,10 @@ if(HAVE_WINDOWS_H)
if(HAVE_LIBWS2_32)
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
endif()
-else(HAVE_WINDOWS_H)
+else()
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
-endif(HAVE_WINDOWS_H)
+endif()
check_c_source_compiles("${_source_epilogue}
int main(void) {
@@ -64,13 +64,13 @@ if(curl_cv_recv)
set(RECV_TYPE_RETV "${recv_retv}")
set(HAVE_RECV 1)
set(curl_cv_func_recv_done 1)
- endif(curl_cv_func_recv_test)
- endif(NOT curl_cv_func_recv_done)
- endforeach(recv_arg4)
- endforeach(recv_arg3)
- endforeach(recv_arg2)
- endforeach(recv_arg1)
- endforeach(recv_retv)
+ endif()
+ endif()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
@@ -81,10 +81,10 @@ if(curl_cv_recv)
if("${curl_cv_func_recv_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for recv args")
- endif("${curl_cv_func_recv_args}" STREQUAL "unknown")
-else(curl_cv_recv)
+ endif()
+else()
message(FATAL_ERROR "Unable to link function recv")
-endif(curl_cv_recv)
+endif()
set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
set(HAVE_RECV 1)
@@ -130,13 +130,13 @@ if(curl_cv_send)
set(SEND_TYPE_RETV "${send_retv}")
set(HAVE_SEND 1)
set(curl_cv_func_send_done 1)
- endif(curl_cv_func_send_test)
- endif(NOT curl_cv_func_send_done)
- endforeach(send_arg4)
- endforeach(send_arg3)
- endforeach(send_arg2)
- endforeach(send_arg1)
- endforeach(send_retv)
+ endif()
+ endif()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
@@ -148,11 +148,11 @@ if(curl_cv_send)
if("${curl_cv_func_send_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for send args")
- endif("${curl_cv_func_send_args}" STREQUAL "unknown")
+ endif()
set(SEND_QUAL_ARG2 "const")
-else(curl_cv_send)
+else()
message(FATAL_ERROR "Unable to link function send")
-endif(curl_cv_send)
+endif()
set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
set(HAVE_SEND 1)
@@ -184,7 +184,7 @@ if(NOT APPLE)
set(CMAKE_REQUIRED_FLAGS)
if(HAVE_SYS_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
- endif(HAVE_SYS_POLL_H)
+ endif()
check_c_source_runs("
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
@@ -199,7 +199,7 @@ set(CMAKE_REQUIRED_FLAGS)
if(HAVE_SIGNAL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H")
set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
-endif(HAVE_SIGNAL_H)
+endif()
check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
if(HAVE_SIZEOF_SIG_ATOMIC_T)
check_c_source_compiles("
@@ -213,8 +213,8 @@ if(HAVE_SIZEOF_SIG_ATOMIC_T)
}" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
set(HAVE_SIG_ATOMIC_T_VOLATILE 1)
- endif(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
-endif(HAVE_SIZEOF_SIG_ATOMIC_T)
+ endif()
+endif()
if(HAVE_WINDOWS_H)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
@@ -222,11 +222,10 @@ else()
set(CMAKE_EXTRA_INCLUDE_FILES)
if(HAVE_SYS_SOCKET_H)
set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
- endif(HAVE_SYS_SOCKET_H)
+ endif()
endif()
check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
-endif(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
-
+endif()
diff --git a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
index 53d0a5e88..2dbe1bbbd 100644
--- a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
+++ b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
@@ -115,8 +115,7 @@ if(NOT UNIX)
set(HAVE_SIGACTION 0)
set(HAVE_MACRO_SIGSETJMP 0)
- else(WIN32)
+ else()
message("This file should be included on Windows platform only")
- endif(WIN32)
-endif(NOT UNIX)
-
+ endif()
+endif()
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index 005b166ff..5cb1d4497 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -1,44 +1,13 @@
# File containing various utilities
-# Converts a CMake list to a string containing elements separated by spaces
-function(TO_LIST_SPACES _LIST_NAME OUTPUT_VAR)
- set(NEW_LIST_SPACE)
- foreach(ITEM ${${_LIST_NAME}})
- set(NEW_LIST_SPACE "${NEW_LIST_SPACE} ${ITEM}")
- endforeach()
- string(STRIP ${NEW_LIST_SPACE} NEW_LIST_SPACE)
- set(${OUTPUT_VAR} "${NEW_LIST_SPACE}" PARENT_SCOPE)
-endfunction()
-
-# Appends a lis of item to a string which is a space-separated list, if they don't already exist.
-function(LIST_SPACES_APPEND_ONCE LIST_NAME)
- string(REPLACE " " ";" _LIST ${${LIST_NAME}})
- list(APPEND _LIST ${ARGN})
- list(REMOVE_DUPLICATES _LIST)
- to_list_spaces(_LIST NEW_LIST_SPACE)
- set(${LIST_NAME} "${NEW_LIST_SPACE}" PARENT_SCOPE)
-endfunction()
-
-# Convenience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value.
-# Ex: IN_STR_LIST(MY_LIST "Searched item" WAS_FOUND)
-function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL)
- list(FIND ${LIST_NAME} ${ITEM_SEARCHED} FIND_POS)
- if(${FIND_POS} EQUAL -1)
- set(${RETVAL} FALSE PARENT_SCOPE)
- else()
- set(${RETVAL} TRUE PARENT_SCOPE)
- endif()
-endfunction()
-
# Returns a list of arguments that evaluate to true
-function(collect_true output_var output_count_var)
- set(${output_var})
+function(count_true output_count_var)
+ set(lst)
foreach(option_var IN LISTS ARGN)
if(${option_var})
- list(APPEND ${output_var} ${option_var})
+ list(APPEND lst ${option_var})
endif()
endforeach()
- set(${output_var} ${${output_var}} PARENT_SCOPE)
- list(LENGTH ${output_var} ${output_count_var})
- set(${output_count_var} ${${output_count_var}} PARENT_SCOPE)
+ list(LENGTH lst lst_len)
+ set(${output_count_var} ${lst_len} PARENT_SCOPE)
endfunction()
diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
index d00a51665..db8e5367d 100644
--- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
+++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
@@ -1,11 +1,11 @@
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
-endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+endif()
-if (NOT DEFINED CMAKE_INSTALL_PREFIX)
- set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
-endif ()
- message(${CMAKE_INSTALL_PREFIX})
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
+endif()
+message(${CMAKE_INSTALL_PREFIX})
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
@@ -19,8 +19,8 @@ foreach(file ${files})
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
- endif(NOT "${rm_retval}" STREQUAL 0)
- else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ endif()
+ else()
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
- endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
-endforeach(file)
+ endif()
+endforeach()
diff --git a/Utilities/cmcurl/CMake/curl-config.cmake b/Utilities/cmcurl/CMake/curl-config.cmake
deleted file mode 100644
index 119332cdd..000000000
--- a/Utilities/cmcurl/CMake/curl-config.cmake
+++ /dev/null
@@ -1,59 +0,0 @@
-
-get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-if(NOT CURL_FIND_COMPONENTS)
- set(CURL_FIND_COMPONENTS curl libcurl)
- if(CURL_FIND_REQUIRED)
- set(CURL_FIND_REQUIRED_curl TRUE)
- set(CURL_FIND_REQUIRED_libcurl TRUE)
- endif()
-endif()
-
-set(_curl_missing_components)
-foreach(_comp ${CURL_FIND_COMPONENTS})
- if(EXISTS "${_DIR}/${_comp}-target.cmake")
- include("${_DIR}/${_comp}-target.cmake")
- set(CURL_${_comp}_FOUND TRUE)
- else()
- set(CURL_${_comp}_FOUND FALSE)
- if(CURL_FIND_REQUIRED_${_comp})
- set(CURL_FOUND FALSE)
- list(APPEND _curl_missing_components ${_comp})
- endif()
- endif()
-endforeach()
-
-if(_curl_missing_components)
- set(CURL_NOT_FOUND_MESSAGE "Following required components not found: " ${_curl_missing_components})
-else()
- if(TARGET CURL::libcurl)
- string(TOUPPER "${CMAKE_BUILD_TYPE}" _curl_current_config)
- if(NOT _curl_current_config)
- set(_curl_current_config "NOCONFIG")
- endif()
- get_target_property(_curl_configurations CURL::libcurl IMPORTED_CONFIGURATIONS)
- list(FIND _curl_configurations "${_curl_current_config}" _i)
- if(_i LESS 0)
- set(_curl_config "RELEASE")
- list(FIND _curl_configurations "${_curl_current_config}" _i)
- if(_i LESS 0)
- set(_curl_config "NOCONFIG")
- list(FIND _curl_configurations "${_curl_current_config}" _i)
- endif()
- endif()
-
- if(_i LESS 0)
- set(_curl_current_config "") # let CMake pick config at random
- else()
- set(_curl_current_config "_${_curl_current_config}")
- endif()
-
- get_target_property(CURL_INCLUDE_DIRS CURL::libcurl INTERFACE_INCLUDE_DIRECTORIES)
- get_target_property(CURL_LIBRARIES CURL::libcurl "LOCATION${_curl_current_config}")
- set(_curl_current_config)
- set(_curl_configurations)
- set(_i)
- endif()
-endif()
-
-unset(_curl_missing_components)
diff --git a/Utilities/cmcurl/CMake/curl-config.cmake.in b/Utilities/cmcurl/CMake/curl-config.cmake.in
new file mode 100644
index 000000000..1294e173a
--- /dev/null
+++ b/Utilities/cmcurl/CMake/curl-config.cmake.in
@@ -0,0 +1,12 @@
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+if(@USE_OPENSSL@)
+ find_dependency(OpenSSL @OPENSSL_VERSION_MAJOR@)
+endif()
+if(@USE_ZLIB@)
+ find_dependency(ZLIB @ZLIB_VERSION_MAJOR@)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
+check_required_components("@PROJECT_NAME@")
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 012821415..27b7507f6 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -2,6 +2,7 @@
set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe")
set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports")
set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs")
+set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries")
set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi")
set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2")
set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP")
@@ -23,7 +24,6 @@ set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
-set(CURL_STATICLIB ON CACHE INTERNAL "Static curl")
set(CURL_WERROR OFF CACHE INTERNAL "Turn compiler warnings into errors")
set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions")
set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support")
@@ -123,26 +123,26 @@ endif()
# To check:
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
-cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
include(Macros)
include(CMakeDependentOption)
include(CheckCCompilerFlag)
-project( CURL C )
+project(CURL C)
if(0) # This code not needed for building within CMake.
message(WARNING "the curl cmake build system is poorly maintained. Be aware")
endif()
-file (READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
-string (REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
+file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
+string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
CURL_VERSION ${CURL_VERSION_H_CONTENTS})
-string (REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
-string (REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
+string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
+string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
-string (REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
+string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
include_regular_expression("^.*$") # Sukender: Is it necessary?
@@ -160,19 +160,19 @@ set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
set(OS "\"${CMAKE_SYSTEM_NAME}\"")
include_directories(${PROJECT_BINARY_DIR}/include/curl)
-include_directories( ${CURL_SOURCE_DIR}/include )
+include_directories(${CURL_SOURCE_DIR}/include)
option(CURL_WERROR "Turn compiler warnings into errors" OFF)
option(PICKY_COMPILER "Enable picky compiler options" ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
-option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
endif()
-CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
+cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
ON "NOT ENABLE_ARES"
OFF)
@@ -180,19 +180,19 @@ option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
- if (PICKY_COMPILER)
- foreach (_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers)
+ if(PICKY_COMPILER)
+ foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format)
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
# test result in.
- CHECK_C_COMPILER_FLAG(${_CCOPT} OPT${_CCOPT})
+ check_c_compiler_flag(${_CCOPT} OPT${_CCOPT})
if(OPT${_CCOPT})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
endif()
endforeach()
- endif(PICKY_COMPILER)
-endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+ endif()
+endif()
-if (ENABLE_DEBUG)
+if(ENABLE_DEBUG)
# DEBUGBUILD will be defined only for Debug builds
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
@@ -202,13 +202,15 @@ if (ENABLE_DEBUG)
set(ENABLE_CURLDEBUG ON)
endif()
-if (ENABLE_CURLDEBUG)
+if(ENABLE_CURLDEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG)
endif()
if(0) # This code not needed for building within CMake.
# For debug libs and exes, add "-d" postfix
-set(CMAKE_DEBUG_POSTFIX "-d" CACHE STRING "Set debug library postfix")
+if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+ set(CMAKE_DEBUG_POSTFIX "-d")
+endif()
endif()
# initialize CURL_LIBS
@@ -217,7 +219,7 @@ set(CURL_LIBS "")
if(ENABLE_ARES)
set(USE_ARES 1)
find_package(CARES REQUIRED)
- list(APPEND CURL_LIBS ${CARES_LIBRARY} )
+ list(APPEND CURL_LIBS ${CARES_LIBRARY})
set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY})
endif()
@@ -297,11 +299,11 @@ if(ENABLE_IPV6 AND NOT WIN32)
endif()
if(0) # This code not needed for building within CMake.
-CURL_NROFF_CHECK()
# Required for building manual, docs, tests
+curl_nroff_check()
find_package(Perl)
-CMAKE_DEPENDENT_OPTION(ENABLE_MANUAL "to provide the built-in manual"
+cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
ON "NROFF_USEFUL;PERL_FOUND"
OFF)
@@ -326,27 +328,27 @@ endif()
# Disable warnings on Borland to avoid changing 3rd party code.
if(BORLAND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
-endif(BORLAND)
+endif()
# If we are on AIX, do the _ALL_SOURCE magic
if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
set(_ALL_SOURCE 1)
-endif(${CMAKE_SYSTEM_NAME} MATCHES AIX)
+endif()
# Include all the necessary files for macros
-include (CheckFunctionExists)
-include (CheckIncludeFile)
-include (CheckIncludeFiles)
-include (CheckLibraryExists)
-include (CheckSymbolExists)
-include (CheckTypeSize)
-include (CheckCSourceCompiles)
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckIncludeFiles)
+include(CheckLibraryExists)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+include(CheckCSourceCompiles)
# On windows preload settings
if(WIN32)
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
-endif(WIN32)
+endif()
if(ENABLE_THREADED_RESOLVER)
find_package(Threads REQUIRED)
@@ -375,13 +377,13 @@ if(BEOS)
set(NOT_NEED_LIBNSL 1)
check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND)
check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI)
-endif(BEOS)
+endif()
check_library_exists_concat("network" recv HAVE_LIBNETWORK)
if(NOT NOT_NEED_LIBNSL)
check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL)
-endif(NOT NOT_NEED_LIBNSL)
+endif()
check_function_exists(gethostname HAVE_GETHOSTNAME)
@@ -409,14 +411,14 @@ if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
set(openssl_default OFF)
endif()
-collect_true(enabled_ssl_options enabled_ssl_options_count
+count_true(enabled_ssl_options_count
CMAKE_USE_WINSSL
CMAKE_USE_DARWINSSL
CMAKE_USE_OPENSSL
CMAKE_USE_MBEDTLS
)
-if(enabled_ssl_options_count GREATER 1)
- message(FATAL_ERROR "Multiple SSL options specified: ${enabled_ssl_options}. Please pick at most one and disable the rest.")
+if(enabled_ssl_options_count GREATER "1")
+ set(CURL_WITH_MULTI_SSL ON)
endif()
if(CMAKE_USE_WINSSL)
@@ -454,9 +456,9 @@ if(CMAKE_USE_OPENSSL)
set(HAVE_LIBSSL ON)
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
include_directories(${OPENSSL_INCLUDE_DIR})
+
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
- check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H)
check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H)
check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H)
@@ -585,7 +587,6 @@ if(NOT CURL_DISABLE_LDAP)
endif()
endif()
endif()
-
endif()
# No ldap, no ldaps.
@@ -611,15 +612,23 @@ if(0) # This code not needed for building within CMake.
option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
-set(HAVE_ZLIB OFF)
+set(USE_ZLIB OFF)
if(CURL_ZLIB)
find_package(ZLIB QUIET)
if(ZLIB_FOUND)
set(HAVE_ZLIB_H ON)
- set(HAVE_ZLIB ON)
set(HAVE_LIBZ ON)
- list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIRS})
+ set(USE_ZLIB ON)
+
+ # Depend on ZLIB via imported targets if supported by the running
+ # version of CMake. This allows our dependents to get our dependencies
+ # transitively.
+ if(NOT CMAKE_VERSION VERSION_LESS 3.4)
+ list(APPEND CURL_LIBS ZLIB::ZLIB)
+ else()
+ list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
+ include_directories(${ZLIB_INCLUDE_DIRS})
+ endif()
list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
endif()
endif()
@@ -677,9 +686,8 @@ if(CMAKE_USE_LIBSSH2)
check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64)
check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
set(CMAKE_EXTRA_INCLUDE_FILES "")
-
- endif(LIBSSH2_FOUND)
-endif(CMAKE_USE_LIBSSH2)
+ endif()
+endif()
option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
mark_as_advanced(CMAKE_USE_GSSAPI)
@@ -761,68 +769,67 @@ set(CURL_CA_PATH "auto" CACHE STRING
"Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
if("${CURL_CA_BUNDLE}" STREQUAL "")
- message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
+ message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
elseif("${CURL_CA_BUNDLE}" STREQUAL "none")
- unset(CURL_CA_BUNDLE CACHE)
+ unset(CURL_CA_BUNDLE CACHE)
elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
- unset(CURL_CA_BUNDLE CACHE)
- set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+ unset(CURL_CA_BUNDLE CACHE)
+ set(CURL_CA_BUNDLE_AUTODETECT TRUE)
else()
- set(CURL_CA_BUNDLE_SET TRUE)
+ set(CURL_CA_BUNDLE_SET TRUE)
endif()
if("${CURL_CA_PATH}" STREQUAL "")
- message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
+ message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
elseif("${CURL_CA_PATH}" STREQUAL "none")
- unset(CURL_CA_PATH CACHE)
+ unset(CURL_CA_PATH CACHE)
elseif("${CURL_CA_PATH}" STREQUAL "auto")
- unset(CURL_CA_PATH CACHE)
- set(CURL_CA_PATH_AUTODETECT TRUE)
+ unset(CURL_CA_PATH CACHE)
+ set(CURL_CA_PATH_AUTODETECT TRUE)
else()
- set(CURL_CA_PATH_SET TRUE)
+ set(CURL_CA_PATH_SET TRUE)
endif()
if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
- # Skip autodetection of unset CA path because CA bundle is set explicitly
+ # Skip autodetection of unset CA path because CA bundle is set explicitly
elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
- # Skip autodetection of unset CA bundle because CA path is set explicitly
+ # Skip autodetection of unset CA bundle because CA path is set explicitly
elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
- # first try autodetecting a CA bundle, then a CA path
-
- if(CURL_CA_BUNDLE_AUTODETECT)
- set(SEARCH_CA_BUNDLE_PATHS
- /etc/ssl/certs/ca-certificates.crt
- /etc/pki/tls/certs/ca-bundle.crt
- /usr/share/ssl/certs/ca-bundle.crt
- /usr/local/share/certs/ca-root-nss.crt
- /etc/ssl/cert.pem)
-
- foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
- if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
- message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
- set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
- set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
- break()
- endif()
- endforeach()
- endif()
+ # first try autodetecting a CA bundle, then a CA path
+
+ if(CURL_CA_BUNDLE_AUTODETECT)
+ set(SEARCH_CA_BUNDLE_PATHS
+ /etc/ssl/certs/ca-certificates.crt
+ /etc/pki/tls/certs/ca-bundle.crt
+ /usr/share/ssl/certs/ca-bundle.crt
+ /usr/local/share/certs/ca-root-nss.crt
+ /etc/ssl/cert.pem)
+
+ foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
+ if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
+ message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
+ set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
+ set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
+ break()
+ endif()
+ endforeach()
+ endif()
- if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
- if(EXISTS "/etc/ssl/certs")
- set(CURL_CA_PATH "/etc/ssl/certs")
- set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
- endif()
+ if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
+ if(EXISTS "/etc/ssl/certs")
+ set(CURL_CA_PATH "/etc/ssl/certs")
+ set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
endif()
+ endif()
endif()
if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
- message(FATAL_ERROR
- "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
- "Set CURL_CA_PATH=none or enable one of those TLS backends.")
+ message(FATAL_ERROR
+ "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
+ "Set CURL_CA_PATH=none or enable one of those TLS backends.")
endif()
endif()
-
# Check for header files
if(NOT UNIX)
check_include_file_concat("windows.h" HAVE_WINDOWS_H)
@@ -920,7 +927,7 @@ check_type_size("time_t" SIZEOF_TIME_T)
if(HAVE_SIZEOF_LONG_LONG)
set(HAVE_LONGLONG 1)
set(HAVE_LL 1)
-endif(HAVE_SIZEOF_LONG_LONG)
+endif()
find_file(RANDOM_FILE urandom /dev)
mark_as_advanced(RANDOM_FILE)
@@ -954,7 +961,7 @@ check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI)
check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
if(NOT HAVE_STRNCMPI)
set(HAVE_STRCMPI)
-endif(NOT HAVE_STRNCMPI)
+endif()
check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
@@ -970,6 +977,7 @@ check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
+check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
@@ -982,7 +990,7 @@ check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
set(HAVE_SIGNAL 1)
-endif(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
+endif()
check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME)
check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
@@ -1016,35 +1024,35 @@ if(WIN32)
add_definitions(-D_WIN32_WINNT=0x0501)
endif()
else()
- check_function_exists(inet_pton HAVE_INET_PTON)
+ check_function_exists(inet_pton HAVE_INET_PTON)
endif()
check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
if(HAVE_FSETXATTR)
foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6)
- curl_internal_test_run(${CURL_TEST})
- endforeach(CURL_TEST)
-endif(HAVE_FSETXATTR)
+ curl_internal_test(${CURL_TEST})
+ endforeach()
+endif()
# sigaction and sigsetjmp are special. Use special mechanism for
# detecting those, but only if previous attempt failed.
if(HAVE_SIGNAL_H)
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
-endif(HAVE_SIGNAL_H)
+endif()
if(NOT HAVE_SIGSETJMP)
if(HAVE_SETJMP_H)
check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
if(HAVE_MACRO_SIGSETJMP)
set(HAVE_SIGSETJMP 1)
- endif(HAVE_MACRO_SIGSETJMP)
- endif(HAVE_SETJMP_H)
-endif(NOT HAVE_SIGSETJMP)
+ endif()
+ endif()
+endif()
# If there is no stricmp(), do not allow LDAP to parse URLs
if(NOT HAVE_STRICMP)
set(HAVE_LDAP_URL_PARSE 1)
-endif(NOT HAVE_STRICMP)
+endif()
# Do curl specific tests
foreach(CURL_TEST
@@ -1071,7 +1079,6 @@ foreach(CURL_TEST
HAVE_GETHOSTBYNAME_R_3_REENTRANT
HAVE_GETHOSTBYNAME_R_5_REENTRANT
HAVE_GETHOSTBYNAME_R_6_REENTRANT
- HAVE_SOCKLEN_T
HAVE_IN_ADDR_T
HAVE_BOOL_T
STDC_HEADERS
@@ -1082,12 +1089,12 @@ foreach(CURL_TEST
HAVE_FILE_OFFSET_BITS
)
curl_internal_test(${CURL_TEST})
-endforeach(CURL_TEST)
+endforeach()
if(HAVE_FILE_OFFSET_BITS)
set(_FILE_OFFSET_BITS 64)
set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
-endif(HAVE_FILE_OFFSET_BITS)
+endif()
check_type_size("off_t" SIZEOF_OFF_T)
# include this header to get the type
@@ -1102,8 +1109,8 @@ foreach(CURL_TEST
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
)
- curl_internal_test_run(${CURL_TEST})
-endforeach(CURL_TEST)
+ curl_internal_test(${CURL_TEST})
+endforeach()
# Check for reentrant
foreach(CURL_TEST
@@ -1117,9 +1124,9 @@ foreach(CURL_TEST
if(NOT ${CURL_TEST})
if(${CURL_TEST}_REENTRANT)
set(NEED_REENTRANT 1)
- endif(${CURL_TEST}_REENTRANT)
- endif(NOT ${CURL_TEST})
-endforeach(CURL_TEST)
+ endif()
+ endif()
+endforeach()
if(NEED_REENTRANT)
foreach(CURL_TEST
@@ -1132,32 +1139,38 @@ if(NEED_REENTRANT)
set(${CURL_TEST} 0)
if(${CURL_TEST}_REENTRANT)
set(${CURL_TEST} 1)
- endif(${CURL_TEST}_REENTRANT)
- endforeach(CURL_TEST)
-endif(NEED_REENTRANT)
+ endif()
+ endforeach()
+endif()
if(HAVE_INET_NTOA_R_DECL_REENTRANT)
set(HAVE_INET_NTOA_R_DECL 1)
set(NEED_REENTRANT 1)
-endif(HAVE_INET_NTOA_R_DECL_REENTRANT)
+endif()
+
+# Check clock_gettime(CLOCK_MONOTONIC, x) support
+curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+# Check compiler support of __builtin_available()
+curl_internal_test(HAVE_BUILTIN_AVAILABLE)
# Some other minor tests
if(NOT HAVE_IN_ADDR_T)
set(in_addr_t "unsigned long")
-endif(NOT HAVE_IN_ADDR_T)
+endif()
# Fix libz / zlib.h
if(NOT CURL_SPECIAL_LIBZ)
if(NOT HAVE_LIBZ)
set(HAVE_ZLIB_H 0)
- endif(NOT HAVE_LIBZ)
+ endif()
if(NOT HAVE_ZLIB_H)
set(HAVE_LIBZ 0)
- endif(NOT HAVE_ZLIB_H)
-endif(NOT CURL_SPECIAL_LIBZ)
+ endif()
+endif()
# Check for nonblocking
set(HAVE_DISABLED_NONBLOCKING 1)
@@ -1166,16 +1179,13 @@ if(HAVE_FIONBIO OR
HAVE_IOCTLSOCKET_CASE OR
HAVE_O_NONBLOCK)
set(HAVE_DISABLED_NONBLOCKING)
-endif(HAVE_FIONBIO OR
- HAVE_IOCTLSOCKET OR
- HAVE_IOCTLSOCKET_CASE OR
- HAVE_O_NONBLOCK)
+endif()
if(RETSIGTYPE_TEST)
set(RETSIGTYPE void)
-else(RETSIGTYPE_TEST)
+else()
set(RETSIGTYPE int)
-endif(RETSIGTYPE_TEST)
+endif()
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
include(CheckCCompilerFlag)
@@ -1185,30 +1195,12 @@ if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS)
if(MPRINTF_COMPILE_FLAGS)
set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double")
- else(MPRINTF_COMPILE_FLAGS)
+ else()
set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
- endif(MPRINTF_COMPILE_FLAGS)
+ endif()
set_source_files_properties(mprintf.c PROPERTIES
COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
- endif(HAVE_C_FLAG_Wno_long_double)
-endif(CMAKE_COMPILER_IS_GNUCC AND APPLE)
-
-if(HAVE_SOCKLEN_T)
- set(CURL_HAVE_SOCKLEN_T 1)
- set(CURL_TYPEOF_CURL_SOCKLEN_T "socklen_t")
- if(WIN32)
- set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h;ws2tcpip.h")
- elseif(HAVE_SYS_SOCKET_H)
- set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
- endif()
- check_type_size("socklen_t" CURL_SIZEOF_CURL_SOCKLEN_T)
- set(CMAKE_EXTRA_INCLUDE_FILES)
- if(NOT HAVE_CURL_SIZEOF_CURL_SOCKLEN_T)
- message(FATAL_ERROR
- "Check for sizeof socklen_t failed, see CMakeFiles/CMakerror.log")
endif()
-else()
- set(CURL_HAVE_SOCKLEN_T 0)
endif()
# TODO test which of these headers are required
@@ -1226,19 +1218,25 @@ include(CMake/OtherTests.cmake)
add_definitions(-DHAVE_CONFIG_H)
-# For windows, all compilers used by cmake should support large files
+# For Windows, all compilers used by CMake should support large files
if(WIN32)
set(USE_WIN32_LARGE_FILES ON)
-endif(WIN32)
+
+ # Use the manifest embedded in the Windows Resource
+ set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
+endif()
if(MSVC)
+ # Disable default manifest added by CMake
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
+
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
- else(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
- endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
-endif(MSVC)
+ endif()
+endif()
if(CURL_WERROR)
if(MSVC_VERSION)
@@ -1247,7 +1245,7 @@ if(CURL_WERROR)
# this assumes clang or gcc style options
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif()
-endif(CURL_WERROR)
+endif()
# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
@@ -1265,10 +1263,14 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
endfunction()
-if(WIN32 AND NOT CYGWIN)
- set(CURL_INSTALL_CMAKE_DIR CMake)
-else()
- set(CURL_INSTALL_CMAKE_DIR lib/cmake/curl)
+if(0) # This code not needed for building within CMake.
+include(GNUInstallDirs)
+
+set(CURL_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
+set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
+set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
+set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
+set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
endif()
if(USE_MANUAL)
@@ -1283,11 +1285,11 @@ endif()
#-----------------------------------------------------------------------------
# CMake-specific curl code.
-add_executable(LIBCURL curltest.c)
-target_link_libraries(LIBCURL cmcurl)
+add_executable(curltest curltest.c)
+target_link_libraries(curltest cmcurl)
-if(CMAKE_CURL_TEST_URL)
- add_test(curl LIBCURL ${CMAKE_CURL_TEST_URL})
+if(BUILD_TESTING AND CMAKE_CURL_TEST_URL)
+ add_test(curl curltest ${CMAKE_CURL_TEST_URL})
endif()
install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
@@ -1381,11 +1383,12 @@ set(CONFIGURE_OPTIONS "")
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
set(CPPFLAG_CURL_STATICLIB "")
set(CURLVERSION "${CURL_VERSION}")
-set(ENABLE_SHARED "yes")
-if(CURL_STATICLIB)
- set(ENABLE_STATIC "yes")
-else()
+if(BUILD_SHARED_LIBS)
+ set(ENABLE_SHARED "yes")
set(ENABLE_STATIC "no")
+else()
+ set(ENABLE_SHARED "no")
+ set(ENABLE_STATIC "yes")
endif()
set(exec_prefix "\${prefix}")
set(includedir "\${prefix}/include")
@@ -1409,10 +1412,13 @@ set(REQUIRE_LIB_DEPS "no")
set(VERSIONNUM "${CURL_VERSION_NUM}")
# Finally generate a "curl-config" matching this config
+# Use:
+# * ENABLE_SHARED
+# * ENABLE_STATIC
configure_file("${CURL_SOURCE_DIR}/curl-config.in"
"${CURL_BINARY_DIR}/curl-config" @ONLY)
install(FILES "${CURL_BINARY_DIR}/curl-config"
- DESTINATION bin
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
@@ -1422,34 +1428,36 @@ install(FILES "${CURL_BINARY_DIR}/curl-config"
configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
"${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
- DESTINATION lib/pkgconfig)
-
-# This needs to be run very last so other parts of the scripts can take advantage of this.
-if(NOT CURL_CONFIG_HAS_BEEN_RUN_BEFORE)
- set(CURL_CONFIG_HAS_BEEN_RUN_BEFORE 1 CACHE INTERNAL "Flag to track whether this is the first time running CMake or if CMake has been configured before")
-endif()
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# install headers
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
- DESTINATION include
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
-
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
- "${PROJECT_BINARY_DIR}/curl-config-version.cmake"
+ "${version_config}"
VERSION ${CURL_VERSION}
COMPATIBILITY SameMajorVersion
)
-configure_file(CMake/curl-config.cmake
- "${PROJECT_BINARY_DIR}/curl-config.cmake"
- COPYONLY
+# Use:
+# * TARGETS_EXPORT_NAME
+# * PROJECT_NAME
+configure_package_config_file(CMake/curl-config.cmake.in
+ "${project_config}"
+ INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
+)
+
+install(
+ EXPORT "${TARGETS_EXPORT_NAME}"
+ NAMESPACE "${PROJECT_NAME}::"
+ DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
install(
- FILES ${PROJECT_BINARY_DIR}/curl-config.cmake
- ${PROJECT_BINARY_DIR}/curl-config-version.cmake
+ FILES ${version_config} ${project_config}
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
diff --git a/Utilities/cmcurl/curltest.c b/Utilities/cmcurl/curltest.c
index 210868e36..f80e758a0 100644
--- a/Utilities/cmcurl/curltest.c
+++ b/Utilities/cmcurl/curltest.c
@@ -1,159 +1,81 @@
-/* Prevent warnings on Visual Studio */
-struct _RPC_ASYNC_STATE;
-
#include "curl/curl.h"
+
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-int GetFtpFile(void)
+int test_curl(const char* url)
{
- int retVal = 0;
- CURL *curl;
- CURLcode res;
- curl = curl_easy_init();
- if(curl)
- {
- /* Get curl 7.9.2 from sunet.se's FTP site: */
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_HEADER, 1);
- curl_easy_setopt(curl, CURLOPT_URL,
- "ftp://public.kitware.com/pub/cmake/cygwin/setup.hint");
- res = curl_easy_perform(curl);
- if ( res != 0 )
- {
- printf("Error fetching: ftp://public.kitware.com/pub/cmake/cygwin/setup.hint\n");
- retVal = 1;
- }
-
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
- else
- {
- printf("Cannot create curl object\n");
- retVal = 1;
- }
- return retVal;
-}
-
-int GetWebFiles(char *url1, char *url2)
-{
- int retVal = 0;
- CURL *curl;
- CURLcode res;
-
+ CURL* curl;
+ CURLcode r;
char proxy[1024];
int proxy_type = 0;
- if ( getenv("HTTP_PROXY") )
- {
+ if (getenv("HTTP_PROXY")) {
proxy_type = 1;
- if (getenv("HTTP_PROXY_PORT") )
- {
+ if (getenv("HTTP_PROXY_PORT")) {
sprintf(proxy, "%s:%s", getenv("HTTP_PROXY"), getenv("HTTP_PROXY_PORT"));
- }
- else
- {
+ } else {
sprintf(proxy, "%s", getenv("HTTP_PROXY"));
- }
- if ( getenv("HTTP_PROXY_TYPE") )
- {
+ }
+ if (getenv("HTTP_PROXY_TYPE")) {
/* HTTP/SOCKS4/SOCKS5 */
- if ( strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0 )
- {
+ if (strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0) {
proxy_type = 1;
- }
- else if ( strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0 )
- {
+ } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0) {
proxy_type = 2;
- }
- else if ( strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0 )
- {
+ } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0) {
proxy_type = 3;
- }
}
}
+ }
curl = curl_easy_init();
- if(curl)
- {
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_HEADER, 1);
-
- /* Using proxy */
- if ( proxy_type > 0 )
- {
- curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
- switch (proxy_type)
- {
- case 2:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
- break;
- case 3:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- break;
- default:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
- }
- }
-
- /* get the first document */
- curl_easy_setopt(curl, CURLOPT_URL, url1);
- res = curl_easy_perform(curl);
- if ( res != 0 )
- {
- printf("Error fetching: %s\n", url1);
- retVal = 1;
- }
+ if (!curl) {
+ fprintf(stderr, "curl_easy_init failed\n");
+ return 1;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1);
+
+ if (proxy_type > 0) {
+ curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
+ switch (proxy_type) {
+ case 2:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+ break;
+ case 3:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ break;
+ default:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ }
+ }
- /* get another document from the same server using the same
- connection */
- /* avoid warnings about url2 since below block is commented out: */
- (void) url2;
- /*
- curl_easy_setopt(curl, CURLOPT_URL, url2);
- res = curl_easy_perform(curl);
- if ( res != 0 )
- {
- printf("Error fetching: %s\n", url2);
- retVal = 1;
- }
- */
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ r = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
- else
- {
- printf("Cannot create curl object\n");
- retVal = 1;
- }
+ if (r != CURLE_OK) {
+ fprintf(stderr, "error: fetching '%s' failed: %s\n", url,
+ curl_easy_strerror(r));
+ return 1;
+ }
- return retVal;
+ return 0;
}
-
-int main(int argc, char **argv)
+int main(int argc, const char* argv[])
{
- int retVal = 0;
-
+ int r;
curl_global_init(CURL_GLOBAL_DEFAULT);
-
- if(argc>1)
- {
- retVal += GetWebFiles(argv[1], 0);
- }
- else
- {
- printf("error: first argument should be a url to download\n");
- retVal = 1;
- }
-
- /* Do not check the output of FTP socks5 cannot handle FTP yet */
- /* GetFtpFile(); */
- /* do not test ftp right now because we don't enable that port */
-
+ if (argc == 2) {
+ r = test_curl(argv[1]);
+ } else {
+ fprintf(stderr, "error: no URL given as first argument\n");
+ r = 1;
+ }
curl_global_cleanup();
-
- return retVal;
+ return r;
}
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index 10e5c494b..63bb291b3 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -146,7 +146,8 @@ typedef enum {
CURLSSLBACKEND_SCHANNEL = 8,
CURLSSLBACKEND_DARWINSSL = 9,
CURLSSLBACKEND_AXTLS = 10,
- CURLSSLBACKEND_MBEDTLS = 11
+ CURLSSLBACKEND_MBEDTLS = 11,
+ CURLSSLBACKEND_MESALINK = 12
} curl_sslbackend;
/* aliases for library clones and renames */
@@ -517,8 +518,7 @@ typedef enum {
CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
CURLE_OBSOLETE50, /* 50 - NOT USED */
- CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
- wasn't verified fine */
+ CURLE_OBSOLETE51, /* 51 - NOT USED */
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
@@ -528,7 +528,8 @@ typedef enum {
CURLE_OBSOLETE57, /* 57 - NOT IN USE */
CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
- CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
+ CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint
+ wasn't verified fine */
CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
@@ -584,6 +585,9 @@ typedef enum {
CURL_LAST /* never use! */
} CURLcode;
+/* added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
@@ -691,6 +695,7 @@ typedef enum {
* CURLAUTH_NTLM - HTTP NTLM authentication
* CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
* CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_BEARER - HTTP Bearer token authentication
* CURLAUTH_ONLY - Use together with a single other type to force no
* authentication or just that single type
* CURLAUTH_ANY - All fine types set
@@ -708,6 +713,7 @@ typedef enum {
#define CURLAUTH_NTLM (((unsigned long)1)<<3)
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
+#define CURLAUTH_BEARER (((unsigned long)1)<<6)
#define CURLAUTH_ONLY (((unsigned long)1)<<31)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
@@ -798,6 +804,9 @@ typedef enum {
this value, keep them in sync. */
#define CURL_HET_DEFAULT 200L
+/* The default connection upkeep interval in milliseconds. */
+#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
@@ -1847,6 +1856,22 @@ typedef enum {
/* shuffle addresses before use when DNS returns multiple */
CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+ /* Specify which TLS 1.3 ciphers suites to use */
+ CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
+ CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
+
+ /* Disallow specifying username/login in URL. */
+ CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+
+ /* DNS-over-HTTPS URL */
+ CINIT(DOH_URL, STRINGPOINT, 279),
+
+ /* Preferred buffer size to use for uploads */
+ CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
+
+ /* Time in ms between connection upkeep calls for long-lived connections. */
+ CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2527,7 +2552,17 @@ typedef enum {
CURLINFO_SCHEME = CURLINFO_STRING + 49,
/* Fill in new entries below here! */
- CURLINFO_LASTONE = 49
+ /* Preferably these would be defined conditionally based on the
+ sizeof curl_off_t being 64-bits */
+ CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
+ CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
+ CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52,
+ CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
+ CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
+ CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55,
+ CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
+
+ CURLINFO_LASTONE = 56
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2570,6 +2605,7 @@ typedef enum {
CURL_LOCK_DATA_DNS,
CURL_LOCK_DATA_SSL_SESSION,
CURL_LOCK_DATA_CONNECT,
+ CURL_LOCK_DATA_PSL,
CURL_LOCK_DATA_LAST
} curl_lock_data;
@@ -2759,6 +2795,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
stuff before they can be included! */
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
+#include "urlapi.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 2d1505aa4..3d7b1fbfe 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -30,12 +30,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.60.0"
+#define LIBCURL_VERSION "7.62.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 60
+#define LIBCURL_VERSION_MINOR 62
#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 0x073C00
+#define LIBCURL_VERSION_NUM 0x073E00
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index 752c5049f..f42a8a969 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/include/curl/easy.h
@@ -95,6 +95,16 @@ CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
size_t buflen, size_t *n);
+
+/*
+ * NAME curl_easy_upkeep()
+ *
+ * DESCRIPTION
+ *
+ * Performs connection upkeep for the given session handle.
+ */
+CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
+
#ifdef __cplusplus
}
#endif
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index eac4cfeb6..1e555ec19 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -298,7 +298,7 @@
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
-#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || \
defined(__sparcv8) || \
@@ -320,6 +320,24 @@
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
+#elif defined(__xlc__) /* IBM xlc compiler */
+# if !defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
/* ===================================== */
/* KEEP MSVC THE PENULTIMATE ENTRY */
/* ===================================== */
@@ -344,7 +362,7 @@
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) && !defined(_SCO_DS)
# if !defined(__LP64__) && \
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 3a0f253f6..244336204 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.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
@@ -269,6 +269,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
(option) == CURLOPT_DNS_SERVERS || \
+ (option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
@@ -428,7 +429,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
* == or whatsoever.
*/
-/* XXX: should evaluate to true iff expr is a pointer */
+/* XXX: should evaluate to true if expr is a pointer */
#define _curl_is_any_ptr(expr) \
(sizeof(expr) == sizeof(void *))
@@ -500,7 +501,8 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define _curl_is_postfields(expr) \
(_curl_is_ptr((expr), void) || \
- _curl_is_arr((expr), char))
+ _curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), unsigned char))
/* FIXME: the whole callback checking is messy...
* The idea is to tolerate char vs. void and const vs. not const
diff --git a/Utilities/cmcurl/include/curl/urlapi.h b/Utilities/cmcurl/include/curl/urlapi.h
new file mode 100644
index 000000000..90dd56c00
--- /dev/null
+++ b/Utilities/cmcurl/include/curl/urlapi.h
@@ -0,0 +1,120 @@
+#ifndef __CURL_URLAPI_H
+#define __CURL_URLAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.
+ *
+ ***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the error codes for the URL API */
+typedef enum {
+ CURLUE_OK,
+ CURLUE_BAD_HANDLE, /* 1 */
+ CURLUE_BAD_PARTPOINTER, /* 2 */
+ CURLUE_MALFORMED_INPUT, /* 3 */
+ CURLUE_BAD_PORT_NUMBER, /* 4 */
+ CURLUE_UNSUPPORTED_SCHEME, /* 5 */
+ CURLUE_URLDECODE, /* 6 */
+ CURLUE_OUT_OF_MEMORY, /* 7 */
+ CURLUE_USER_NOT_ALLOWED, /* 8 */
+ CURLUE_UNKNOWN_PART, /* 9 */
+ CURLUE_NO_SCHEME, /* 10 */
+ CURLUE_NO_USER, /* 11 */
+ CURLUE_NO_PASSWORD, /* 12 */
+ CURLUE_NO_OPTIONS, /* 13 */
+ CURLUE_NO_HOST, /* 14 */
+ CURLUE_NO_PORT, /* 15 */
+ CURLUE_NO_QUERY, /* 16 */
+ CURLUE_NO_FRAGMENT /* 17 */
+} CURLUcode;
+
+typedef enum {
+ CURLUPART_URL,
+ CURLUPART_SCHEME,
+ CURLUPART_USER,
+ CURLUPART_PASSWORD,
+ CURLUPART_OPTIONS,
+ CURLUPART_HOST,
+ CURLUPART_PORT,
+ CURLUPART_PATH,
+ CURLUPART_QUERY,
+ CURLUPART_FRAGMENT
+} CURLUPart;
+
+#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
+#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
+ if the port number matches the
+ default for the scheme */
+#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
+ missing */
+#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
+#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
+#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
+#define CURLU_URLDECODE (1<<6) /* URL decode on get */
+#define CURLU_URLENCODE (1<<7) /* URL encode on set */
+#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
+#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
+
+typedef struct Curl_URL CURLU;
+
+/*
+ * curl_url() creates a new CURLU handle and returns a pointer to it.
+ * Must be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url(void);
+
+/*
+ * curl_url_cleanup() frees the CURLU handle and related resources used for
+ * the URL parsing. It will not free strings previously returned with the URL
+ * API.
+ */
+CURL_EXTERN void curl_url_cleanup(CURLU *handle);
+
+/*
+ * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
+ * handle must also be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
+
+/*
+ * curl_url_get() extracts a specific part of the URL from a CURLU
+ * handle. Returns error code. The returned pointer MUST be freed with
+ * curl_free() afterwards.
+ */
+CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
+ char **part, unsigned int flags);
+
+/*
+ * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
+ * error code. The passed in string will be copied. Passing a NULL instead of
+ * a part string, clears that part.
+ */
+CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
+ const char *part, unsigned int flags);
+
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index 9f19daa79..2a6279c29 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -1,5 +1,13 @@
set(LIB_NAME cmcurl)
+if(BUILD_SHARED_LIBS)
+ set(CURL_STATICLIB NO)
+else()
+ set(CURL_STATICLIB YES)
+endif()
+
+# Use:
+# * CURL_STATICLIB
configure_file(curl_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
@@ -59,14 +67,6 @@ if(USE_ARES)
include_directories(${CARES_INCLUDE_DIR})
endif()
-if(CURL_STATICLIB)
- # Static lib
- set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC STATIC)
-else()
- # DLL / so dynamic lib
- set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC SHARED)
-endif()
-
# For windows we want to install OPENSSL_LIBRARIES dlls
# and also copy them into the build tree so that testing
# can find them.
@@ -93,16 +93,19 @@ endif()
add_library(
${LIB_NAME}
- ${CURL_USER_DEFINED_DYNAMIC_OR_STATIC}
${HHEADERS} ${CSOURCES}
${CMAKE_CURL_SSL_DLLS}
)
+if(NOT BUILD_SHARED_LIBS)
+ set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
+endif()
+
target_link_libraries(${LIB_NAME} ${CURL_LIBS})
if(0) # This code not needed for building within CMake.
if(WIN32)
- add_definitions( -D_USRDLL )
+ add_definitions(-D_USRDLL)
endif()
endif()
@@ -119,27 +122,21 @@ set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
if(WIN32)
- if(NOT CURL_STATICLIB)
+ if(BUILD_SHARED_LIBS)
# Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
-
- set_target_properties (${LIB_NAME} PROPERTIES
- DEBUG_POSTFIX "-d"
- # Note: no postfix for release variants, let user choose what style of release he wants
- # MINSIZEREL_POSTFIX "-z"
- # RELWITHDEBINFO_POSTFIX "-g"
- )
endif()
endif()
target_include_directories(${LIB_NAME} INTERFACE
- $<INSTALL_INTERFACE:include>)
+ $<INSTALL_INTERFACE:include>
+ $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
install(TARGETS ${LIB_NAME}
- EXPORT libcurl-target
- ARCHIVE DESTINATION lib
- LIBRARY DESTINATION lib
- RUNTIME DESTINATION bin
+ EXPORT ${TARGETS_EXPORT_NAME}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
export(TARGETS ${LIB_NAME}
@@ -147,10 +144,4 @@ export(TARGETS ${LIB_NAME}
NAMESPACE CURL::
)
-install(EXPORT libcurl-target
- FILE libcurl-target.cmake
- NAMESPACE CURL::
- DESTINATION ${CURL_INSTALL_CMAKE_DIR}
-)
-
endif()
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 61c23411d..4aa042259 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -30,12 +30,12 @@ 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/schannel_verify.c \
- vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c
+ vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.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 \
vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \
- vtls/mbedtls.h
+ vtls/mbedtls.h vtls/mesalink.h
LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
@@ -54,7 +54,8 @@ 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 curl_ctype.c curl_range.c
+ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \
+ doh.c urlapi.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 +75,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_ctype.h curl_range.h
+ curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h
LIB_RCFILES = libcurl.rc
diff --git a/Utilities/cmcurl/lib/amigaos.h b/Utilities/cmcurl/lib/amigaos.h
index 02bee1610..7c0926cc3 100644
--- a/Utilities/cmcurl/lib/amigaos.h
+++ b/Utilities/cmcurl/lib/amigaos.h
@@ -36,4 +36,3 @@ void Curl_amiga_cleanup();
#endif
#endif /* HEADER_CURL_AMIGAOS_H */
-
diff --git a/Utilities/cmcurl/lib/arpa_telnet.h b/Utilities/cmcurl/lib/arpa_telnet.h
index ec238729d..232680e7d 100644
--- a/Utilities/cmcurl/lib/arpa_telnet.h
+++ b/Utilities/cmcurl/lib/arpa_telnet.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, 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 @@
#define CURL_NEW_ENV_VAR 0
#define CURL_NEW_ENV_VALUE 1
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
/*
* The telnet options represented as strings
*/
@@ -53,6 +54,7 @@ static const char * const telnetoptions[]=
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
+#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
@@ -76,6 +78,7 @@ static const char * const telnetoptions[]=
#define CURL_DONT 254 /* DON'T use this option! */
#define CURL_IAC 255 /* Interpret As Command */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
/*
* Then those numbers represented as strings:
*/
@@ -86,6 +89,7 @@ static const char * const telnetcmds[]=
"AYT", "EC", "EL", "GA", "SB",
"WILL", "WONT", "DO", "DONT", "IAC"
};
+#endif
#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index aa581a49a..5cfb2602d 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.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
@@ -312,22 +312,25 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
conn->async.os_specific;
CURLcode result = CURLE_OK;
- *dns = NULL;
+ if(dns)
+ *dns = NULL;
waitperform(conn, 0);
if(res && !res->num_pending) {
- (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
- /* temp_ai ownership is moved to the connection, so we need not free-up
- them */
- res->temp_ai = NULL;
+ if(dns) {
+ (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ /* temp_ai ownership is moved to the connection, so we need not free-up
+ them */
+ res->temp_ai = NULL;
+ }
if(!conn->async.dns) {
failf(data, "Could not resolve: %s (%s)",
conn->async.hostname, ares_strerror(conn->async.status));
result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
- else
+ else if(dns)
*dns = conn->async.dns;
destroy_async_data(&conn->async);
@@ -390,7 +393,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
timeout_ms = 1000;
waitperform(conn, timeout_ms);
- result = Curl_resolver_is_resolved(conn, &temp_entry);
+ result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL);
if(result || conn->async.done)
break;
@@ -472,17 +475,19 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
return;
res = (struct ResolverResults *)conn->async.os_specific;
- res->num_pending--;
+ if(res) {
+ res->num_pending--;
- if(CURL_ASYNC_SUCCESS == status) {
- Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
- if(ai) {
- compound_results(res, ai);
+ if(CURL_ASYNC_SUCCESS == status) {
+ Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ if(ai) {
+ compound_results(res, ai);
+ }
}
+ /* A successful result overwrites any previous error */
+ if(res->last_status != ARES_SUCCESS)
+ res->last_status = status;
}
- /* A successful result overwrites any previous error */
- if(res->last_status != ARES_SUCCESS)
- res->last_status = status;
}
/*
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index b11fab246..2a59294e5 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -182,8 +182,6 @@ static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
return &(((struct thread_data *)conn->async.os_specific)->tsd);
}
-#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
-
/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data * tsd)
@@ -481,8 +479,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
DEBUGASSERT(conn && td);
/* wait for the thread to resolve the name */
- if(Curl_thread_join(&td->thread_hnd))
- result = getaddrinfo_complete(conn);
+ if(Curl_thread_join(&td->thread_hnd)) {
+ if(entry)
+ result = getaddrinfo_complete(conn);
+ }
else
DEBUGASSERT(0);
@@ -572,10 +572,10 @@ int Curl_resolver_getsock(struct connectdata *conn,
(void)socks;
(void)numsocks;
ms = Curl_timediff(Curl_now(), reslv->start);
- if(ms < 10)
- milli = ms/3;
+ if(ms < 3)
+ milli = 0;
else if(ms <= 50)
- milli = 10;
+ milli = ms/3;
else if(ms <= 250)
milli = 50;
else
diff --git a/Utilities/cmcurl/lib/base64.c b/Utilities/cmcurl/lib/base64.c
index 204a2273d..6370e4cdf 100644
--- a/Utilities/cmcurl/lib/base64.c
+++ b/Utilities/cmcurl/lib/base64.c
@@ -49,13 +49,12 @@ static size_t decodeQuantum(unsigned char *dest, const char *src)
unsigned long i, x = 0;
for(i = 0, s = src; i < 4; i++, s++) {
- unsigned long v = 0;
-
if(*s == '=') {
x = (x << 6);
padding++;
}
else {
+ unsigned long v = 0;
p = base64;
while(*p && (*p != *s)) {
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index b8f544485..6fbf3b1d2 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
- * 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
@@ -63,10 +63,9 @@
static void conn_llist_dtor(void *user, void *element)
{
- struct connectdata *data = element;
+ struct connectdata *conn = element;
(void)user;
-
- data->bundle = NULL;
+ conn->bundle = NULL;
}
static CURLcode bundle_create(struct Curl_easy *data,
@@ -96,14 +95,13 @@ static void bundle_destroy(struct connectbundle *cb_ptr)
}
/* Add a connection to a bundle */
-static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
- struct connectdata *conn)
+static void bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
{
Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
&conn->bundle_node);
conn->bundle = cb_ptr;
cb_ptr->num_connections++;
- return CURLE_OK;
}
/* Remove a connection from a bundle */
@@ -263,7 +261,7 @@ static void conncache_remove_bundle(struct conncache *connc,
CURLcode Curl_conncache_add_conn(struct conncache *connc,
struct connectdata *conn)
{
- CURLcode result;
+ CURLcode result = CURLE_OK;
struct connectbundle *bundle;
struct connectbundle *new_bundle = NULL;
struct Curl_easy *data = conn->data;
@@ -290,19 +288,13 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
bundle = new_bundle;
}
- result = bundle_add_conn(bundle, conn);
- if(result) {
- if(new_bundle)
- conncache_remove_bundle(data->state.conn_cache, new_bundle);
- goto unlock;
- }
-
+ bundle_add_conn(bundle, conn);
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
DEBUGF(infof(conn->data, "Added connection %ld. "
- "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n",
- conn->connection_id, (curl_off_t) connc->num_conn));
+ "The cache now contains %zu members\n",
+ conn->connection_id, connc->num_conn));
unlock:
CONN_UNLOCK(data);
@@ -320,7 +312,7 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
due to a failed connection attempt, before being added to a bundle */
if(bundle) {
if(lock) {
- CONN_LOCK(conn->data);
+ CONN_LOCK(data);
}
bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0)
@@ -328,12 +320,11 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
conn->bundle = NULL; /* removed from it */
if(connc) {
connc->num_conn--;
- DEBUGF(infof(conn->data, "The cache now contains %"
- CURL_FORMAT_CURL_OFF_TU " members\n",
- (curl_off_t) connc->num_conn));
+ DEBUGF(infof(data, "The cache now contains %zu members\n",
+ connc->num_conn));
}
if(lock) {
- CONN_UNLOCK(conn->data);
+ CONN_UNLOCK(data);
}
}
}
@@ -441,18 +432,11 @@ bool Curl_conncache_return_conn(struct connectdata *conn)
infof(data, "Connection cache is full, closing the oldest one.\n");
conn_candidate = Curl_conncache_extract_oldest(data);
-
if(conn_candidate) {
- /* Set the connection's owner correctly */
- conn_candidate->data = data;
-
/* the winner gets the honour of being disconnected */
- (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
}
}
- CONN_LOCK(data);
- conn->inuse = FALSE; /* Mark the connection unused */
- CONN_UNLOCK(data);
return (conn_candidate == conn) ? FALSE : TRUE;
@@ -486,7 +470,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
while(curr) {
conn = curr->ptr;
- if(!conn->inuse) {
+ if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->now);
@@ -501,9 +485,9 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle, conn_candidate);
data->state.conn_cache->num_conn--;
- DEBUGF(infof(data, "The cache now contains %"
- CURL_FORMAT_CURL_OFF_TU " members\n",
- (curl_off_t) data->state.conn_cache->num_conn));
+ DEBUGF(infof(data, "The cache now contains %zu members\n",
+ data->state.conn_cache->num_conn));
+ conn_candidate->data = data; /* associate! */
}
return conn_candidate;
@@ -544,7 +528,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
while(curr) {
conn = curr->ptr;
- if(!conn->inuse) {
+ if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->now);
@@ -563,9 +547,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle_candidate, conn_candidate);
connc->num_conn--;
- DEBUGF(infof(data, "The cache now contains %"
- CURL_FORMAT_CURL_OFF_TU " members\n",
- (curl_off_t) connc->num_conn));
+ DEBUGF(infof(data, "The cache now contains %zu members\n",
+ connc->num_conn));
+ conn_candidate->data = data; /* associate! */
}
CONN_UNLOCK(data);
@@ -586,7 +570,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
pointer */
/* This will remove the connection from the cache */
connclose(conn, "kill all");
- (void)Curl_disconnect(conn, FALSE);
+ (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st);
conn = Curl_conncache_find_first_connection(connc);
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index d8ad80f96..eedd7a800 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
@@ -63,7 +63,7 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn);
bool Curl_conncache_return_conn(struct connectdata *conn);
CURLcode Curl_conncache_add_conn(struct conncache *connc,
- struct connectdata *conn);
+ struct connectdata *conn) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct connectdata *conn,
bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 1a27ae135..41f220268 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.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
@@ -1237,8 +1237,6 @@ static int conn_is_conn(struct connectdata *conn, void *param)
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp)
{
- curl_socket_t sockfd;
-
DEBUGASSERT(data);
/* this works for an easy handle:
@@ -1261,15 +1259,15 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
return CURL_SOCKET_BAD;
}
- if(connp)
+ if(connp) {
/* only store this if the caller cares for it */
*connp = c;
- sockfd = c->sock[FIRSTSOCKET];
+ c->data = data;
+ }
+ return c->sock[FIRSTSOCKET];
}
else
return CURL_SOCKET_BAD;
-
- return sockfd;
}
/*
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index 7c979efcc..6d4753788 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.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
@@ -71,13 +71,13 @@
#define RESERVED 0xE0 /* bits 5..7: reserved */
typedef enum {
- ZLIB_UNINIT, /* uninitialized */
- ZLIB_INIT, /* initialized */
- ZLIB_INFLATING, /* Inflating started. */
- ZLIB_GZIP_HEADER, /* reading gzip header */
- ZLIB_GZIP_TRAILER, /* reading gzip trailer */
- ZLIB_GZIP_INFLATING, /* inflating gzip stream */
- ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
+ ZLIB_UNINIT, /* uninitialized */
+ ZLIB_INIT, /* initialized */
+ ZLIB_INFLATING, /* inflating started. */
+ ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
+ ZLIB_GZIP_HEADER, /* reading gzip header */
+ ZLIB_GZIP_INFLATING, /* inflating gzip stream */
+ ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
/* Writer parameters. */
@@ -150,8 +150,8 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
if(result || !zp->trailerlen)
result = exit_zlib(conn, z, &zp->zlib_init, result);
else {
- /* Only occurs for gzip with zlib < 1.2.0.4. */
- zp->zlib_init = ZLIB_GZIP_TRAILER;
+ /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
+ zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
}
return result;
}
@@ -163,7 +163,6 @@ static CURLcode inflate_stream(struct connectdata *conn,
z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
- int status; /* zlib status */
bool done = FALSE;
CURLcode result = CURLE_OK; /* Curl_client_write status */
char *decomp; /* Put the decompressed data here. */
@@ -184,13 +183,20 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via downstream_write function. */
while(!done) {
+ int status; /* zlib status */
done = TRUE;
/* (re)set buffer for decompressed output for every iteration */
z->next_out = (Bytef *) decomp;
z->avail_out = DSIZ;
+#ifdef Z_BLOCK
+ /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
status = inflate(z, Z_BLOCK);
+#else
+ /* fallback for zlib ver. < 1.2.0.5 */
+ status = inflate(z, Z_SYNC_FLUSH);
+#endif
/* Flush output data if some. */
if(z->avail_out != DSIZ) {
@@ -227,6 +233,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
z->next_in = orig_in;
z->avail_in = nread;
zp->zlib_init = ZLIB_INFLATING;
+ zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
done = FALSE;
break;
}
@@ -281,6 +288,9 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
+ if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
+ return process_trailer(conn, zp);
+
/* Now uncompress the data */
return inflate_stream(conn, writer, ZLIB_INFLATING);
}
@@ -526,7 +536,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
}
break;
- case ZLIB_GZIP_TRAILER:
+ case ZLIB_EXTERNAL_TRAILER:
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
return process_trailer(conn, zp);
@@ -755,7 +765,6 @@ char *Curl_all_content_encodings(void)
const content_encoding * const *cep;
const content_encoding *ce;
char *ace;
- char *p;
for(cep = encodings; *cep; cep++) {
ce = *cep;
@@ -768,7 +777,7 @@ char *Curl_all_content_encodings(void)
ace = malloc(len);
if(ace) {
- p = ace;
+ char *p = ace;
for(cep = encodings; *cep; cep++) {
ce = *cep;
if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
@@ -915,10 +924,9 @@ void Curl_unencode_cleanup(struct connectdata *conn)
static const content_encoding *find_encoding(const char *name, size_t len)
{
const content_encoding * const *cep;
- const content_encoding *ce;
for(cep = encodings; *cep; cep++) {
- ce = *cep;
+ const content_encoding *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce;
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 2c028b381..a342c61de 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -40,7 +40,7 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
received from a server.
The function need to replace previously stored lines that this new
- line superceeds.
+ line supersedes.
It may remove lines that are expired.
@@ -84,12 +84,9 @@ Example set of cookies:
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-#ifdef USE_LIBPSL
-# include <libpsl.h>
-#endif
-
#include "urldata.h"
#include "cookie.h"
+#include "psl.h"
#include "strtok.h"
#include "sendf.h"
#include "slist.h"
@@ -253,9 +250,9 @@ static const char *get_top_domain(const char * const domain, size_t *outlen)
len = strlen(domain);
last = memrchr(domain, '.', len);
if(last) {
- first = memrchr(domain, '.', (size_t) (last - domain));
+ first = memrchr(domain, '.', (last - domain));
if(first)
- len -= (size_t) (++first - domain);
+ len -= (++first - domain);
}
if(outlen)
@@ -379,13 +376,13 @@ static void strstore(char **str, const char *newstr)
*/
static void remove_expired(struct CookieInfo *cookies)
{
- struct Cookie *co, *nx, *pv;
+ struct Cookie *co, *nx;
curl_off_t now = (curl_off_t)time(NULL);
unsigned int i;
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ struct Cookie *pv = NULL;
co = cookies->cookies[i];
- pv = NULL;
while(co) {
nx = co->next;
if(co->expires && co->expires < now) {
@@ -406,6 +403,12 @@ static void remove_expired(struct CookieInfo *cookies)
}
}
+/* Make sure domain contains a dot or is localhost. */
+static bool bad_domain(const char *domain)
+{
+ return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
+}
+
/****************************************************************************
*
* Curl_cookie_add()
@@ -442,10 +445,6 @@ Curl_cookie_add(struct Curl_easy *data,
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
size_t myhash;
-#ifdef USE_LIBPSL
- const psl_ctx_t *psl;
-#endif
-
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -497,7 +496,7 @@ Curl_cookie_add(struct Curl_easy *data,
name + contents. Chrome and Firefox support 4095 or 4096 bytes
combo. */
freecookie(co);
- infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
+ infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
nlen, len);
return NULL;
}
@@ -585,13 +584,8 @@ Curl_cookie_add(struct Curl_easy *data,
* TLD or otherwise "protected" suffix. To reduce risk, we require a
* dot OR the exact host name being "localhost".
*/
- {
- const char *dotp;
- /* check for more dots */
- dotp = strchr(whatptr, '.');
- if(!dotp && !strcasecompare("localhost", whatptr))
- domain = ":";
- }
+ if(bad_domain(whatptr))
+ domain = ":";
#endif
is_ip = isip(domain ? domain : whatptr);
@@ -723,9 +717,9 @@ Curl_cookie_add(struct Curl_easy *data,
if(!queryp)
endslash = strrchr(path, '/');
else
- endslash = memrchr(path, '/', (size_t)(queryp - path));
+ endslash = memrchr(path, '/', (queryp - path));
if(endslash) {
- size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
+ size_t pathlen = (endslash-path + 1); /* include end slash */
co->path = malloc(pathlen + 1); /* one extra for the zero byte */
if(co->path) {
memcpy(co->path, path, pathlen);
@@ -880,9 +874,10 @@ Curl_cookie_add(struct Curl_easy *data,
}
co->livecookie = c->running;
+ co->creationtime = ++c->lastct;
/* now, we have parsed the incoming line, we must now check if this
- superceeds an already existing cookie, which it may if the previous have
+ supersedes an already existing cookie, which it may if the previous have
the same domain and path as this */
/* at first, remove expired cookies */
@@ -890,14 +885,21 @@ Curl_cookie_add(struct Curl_easy *data,
remove_expired(c);
#ifdef USE_LIBPSL
- /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
- This needs a libpsl compiled with builtin data. */
+ /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */
if(domain && co->domain && !isip(co->domain)) {
- psl = psl_builtin();
- if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
- infof(data,
- "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
- co->name, domain, co->domain);
+ const psl_ctx_t *psl = Curl_psl_use(data);
+ int acceptable;
+
+ if(psl) {
+ acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
+ Curl_psl_release(data);
+ }
+ else
+ acceptable = !bad_domain(domain);
+
+ if(!acceptable) {
+ infof(data, "cookie '%s' dropped, domain '%s' must not "
+ "set cookies for '%s'\n", co->name, domain, co->domain);
freecookie(co);
return NULL;
}
@@ -951,6 +953,9 @@ Curl_cookie_add(struct Curl_easy *data,
if(replace_old) {
co->next = clist->next; /* get the next-pointer first */
+ /* when replacing, creationtime is kept from old */
+ co->creationtime = clist->creationtime;
+
/* then free all the old pointers */
free(clist->name);
free(clist->value);
@@ -1140,12 +1145,24 @@ static int cookie_sort(const void *p1, const void *p2)
if(l1 != l2)
return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
- /* 3 - compare cookie names */
- if(c1->name && c2->name)
- return strcmp(c1->name, c2->name);
+ /* 3 - compare cookie name lengths */
+ l1 = c1->name ? strlen(c1->name) : 0;
+ l2 = c2->name ? strlen(c2->name) : 0;
- /* sorry, can't be more deterministic */
- return 0;
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1;
+
+ /* 4 - compare cookie creation time */
+ return (c2->creationtime > c1->creationtime) ? 1 : -1;
+}
+
+/* sort cookies only according to creation time */
+static int cookie_sort_ct(const void *p1, const void *p2)
+{
+ struct Cookie *c1 = *(struct Cookie **)p1;
+ struct Cookie *c2 = *(struct Cookie **)p2;
+
+ return (c2->creationtime > c1->creationtime) ? 1 : -1;
}
#define CLONE(field) \
@@ -1174,6 +1191,7 @@ static struct Cookie *dup_cookie(struct Cookie *src)
d->secure = src->secure;
d->livecookie = src->livecookie;
d->httponly = src->httponly;
+ d->creationtime = src->creationtime;
}
return d;
@@ -1200,7 +1218,6 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
{
struct Cookie *newco;
struct Cookie *co;
- time_t now = time(NULL);
struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
@@ -1218,11 +1235,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
co = c->cookies[myhash];
while(co) {
- /* only process this cookie if it is not expired or had no expire
- date AND that if the cookie requires we're secure we must only
- continue if we are! */
- if((!co->expires || (co->expires > now)) &&
- (co->secure?secure:TRUE)) {
+ /* if the cookie requires we're secure we must only continue if we are! */
+ if(co->secure?secure:TRUE) {
/* now check if the domain is correct */
if(!co->domain ||
@@ -1248,12 +1262,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
matches++;
}
- else {
- fail:
- /* failure, clear up the allocated chain and return NULL */
- Curl_cookie_freelist(mainco);
- return NULL;
- }
+ else
+ goto fail;
}
}
}
@@ -1291,6 +1301,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
}
return mainco; /* return the new list */
+
+fail:
+ /* failure, clear up the allocated chain and return NULL */
+ Curl_cookie_freelist(mainco);
+ return NULL;
}
/*****************************************************************************
@@ -1384,9 +1399,8 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
- unsigned int i;
-
if(c) {
+ unsigned int i;
free(c->filename);
for(i = 0; i < COOKIE_HASH_SIZE; i++)
Curl_cookie_freelist(c->cookies[i]);
@@ -1439,6 +1453,8 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
bool use_stdout = FALSE;
char *format_ptr;
unsigned int i;
+ unsigned int j;
+ struct Cookie **array;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
@@ -1452,6 +1468,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
if(0 == c->numcookies)
return 0;
+ array = malloc(sizeof(struct Cookie *) * c->numcookies);
+ if(!array)
+ return 1;
+
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
@@ -1459,8 +1479,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
}
else {
out = fopen(dumphere, FOPEN_WRITETEXT);
- if(!out)
+ if(!out) {
+ free(array);
return 1; /* failure */
+ }
}
fputs("# Netscape HTTP Cookie File\n"
@@ -1468,22 +1490,32 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
+ j = 0;
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);
+ array[j++] = co;
}
}
+ qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+
+ for(i = 0; i < j; i++) {
+ format_ptr = get_netscape_format(array[i]);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ free(array);
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
+ }
+
+ free(array);
+
if(!use_stdout)
fclose(out);
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index 79b5928dc..a9f90ca71 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -34,7 +34,7 @@ struct Cookie {
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
- bool tailmatch; /* weather we do tail-matchning of the domain name */
+ bool tailmatch; /* whether we do tail-matching of the domain name */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */
@@ -43,6 +43,7 @@ struct Cookie {
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
bool httponly; /* true if the httponly directive is present */
+ int creationtime; /* time when the cookie was written */
};
#define COOKIE_HASH_SIZE 256
@@ -55,6 +56,7 @@ struct CookieInfo {
bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */
bool newsession; /* new session, discard session cookies on load */
+ int lastct; /* last creation-time used in the jar */
};
/* This is the maximum line length we accept for a cookie line. RFC 2109
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 55d5a3942..fd49679c9 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -536,7 +536,8 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
}
#endif
-#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
+ defined(HAVE_FREEADDRINFO)
/*
* curl_dofreeaddrinfo()
*
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 24d1ca0bd..d5e3a90cf 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -118,6 +118,9 @@
/* Define to 1 if bool is an available type. */
#cmakedefine HAVE_BOOL_T 1
+/* Define to 1 if you have the __builtin_available function. */
+#cmakedefine HAVE_BUILTIN_AVAILABLE 1
+
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
@@ -226,6 +229,9 @@
/* Define to 1 if you have the `getpwuid' function. */
#cmakedefine HAVE_GETPWUID 1
+/* Define to 1 if you have the `getpwuid_r' function. */
+#cmakedefine HAVE_GETPWUID_R 1
+
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT 1
@@ -876,6 +882,12 @@
/* The size of `long', as computed by sizeof. */
@SIZEOF_LONG_CODE@
+/* The size of `long long', as computed by sizeof. */
+@SIZEOF_LONG_LONG_CODE@
+
+/* The size of `__int64', as computed by sizeof. */
+@SIZEOF___INT64_CODE@
+
/* The size of `off_t', as computed by sizeof. */
@SIZEOF_OFF_T_CODE@
@@ -951,6 +963,9 @@
/* to enable Windows SSL */
#cmakedefine USE_SCHANNEL 1
+/* enable multiple SSL backends */
+#cmakedefine CURL_WITH_MULTI_SSL 1
+
/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
#cmakedefine USE_YASSLEMUL 1
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index 0179a4f71..fbfd85c43 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -30,6 +30,17 @@
/* The last #include file should be: */
#include "memdebug.h"
+#ifndef HAVE_FNMATCH
+
+/*
+ * TODO:
+ *
+ * Make this function match POSIX. Test 1307 includes a set of test patterns
+ * that returns different results with a POSIX fnmatch() than with this
+ * implementation and this is considered a bug where POSIX is the guiding
+ * light.
+ */
+
#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
@@ -334,9 +345,9 @@ static int loop(const unsigned char *pattern, const unsigned char *string,
s++;
break;
}
+ /* Syntax error in set; mismatch! */
+ return CURL_FNMATCH_NOMATCH;
- /* Syntax error in set: this must be taken as a regular character. */
- /* FALLTHROUGH */
default:
if(*p++ != *s++)
return CURL_FNMATCH_NOMATCH;
@@ -355,5 +366,31 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
- return loop((unsigned char *)pattern, (unsigned char *)string, 5);
+ return loop((unsigned char *)pattern, (unsigned char *)string, 2);
+}
+#else
+#include <fnmatch.h>
+/*
+ * @unittest: 1307
+ */
+int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
+{
+ int rc;
+ (void)ptr; /* the argument is specified by the curl_fnmatch_callback
+ prototype, but not used by Curl_fnmatch() */
+ if(!pattern || !string) {
+ return CURL_FNMATCH_FAIL;
+ }
+ rc = fnmatch(pattern, string, 0);
+ switch(rc) {
+ case 0:
+ return CURL_FNMATCH_MATCH;
+ case FNM_NOMATCH:
+ return CURL_FNMATCH_NOMATCH;
+ default:
+ return CURL_FNMATCH_FAIL;
+ }
+ /* not reached */
}
+
+#endif
diff --git a/Utilities/cmcurl/lib/curl_ldap.h b/Utilities/cmcurl/lib/curl_ldap.h
index 27d03810f..94c002948 100644
--- a/Utilities/cmcurl/lib/curl_ldap.h
+++ b/Utilities/cmcurl/lib/curl_ldap.h
@@ -32,4 +32,3 @@ extern const struct Curl_handler Curl_handler_ldaps;
#endif
#endif /* HEADER_CURL_LDAP_H */
-
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index e27cab353..922e85a92 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -557,8 +557,11 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
unsigned char *ntbuffer /* 21 bytes */)
{
size_t len = strlen(password);
- unsigned char *pw = len ? malloc(len * 2) : strdup("");
+ unsigned char *pw;
CURLcode result;
+ if(len > SIZE_T_MAX/2) /* avoid integer overflow */
+ return CURLE_OUT_OF_MEMORY;
+ pw = len ? malloc(len * 2) : strdup("");
if(!pw)
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 353a65645..a4791eb41 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.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
@@ -249,6 +249,9 @@ done:
return CURLE_REMOTE_ACCESS_DENIED;
}
+/* if larger than this, something is seriously wrong */
+#define MAX_NTLM_WB_RESPONSE 100000
+
static CURLcode ntlm_wb_response(struct connectdata *conn,
const char *input, curlntlm state)
{
@@ -289,6 +292,13 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
buf[len_out - 1] = '\0';
break;
}
+
+ if(len_out > MAX_NTLM_WB_RESPONSE) {
+ failf(conn->data, "too large ntlm_wb response!");
+ free(buf);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
if(!newbuf)
return CURLE_OUT_OF_MEMORY;
@@ -314,6 +324,8 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
free(buf);
+ if(!conn->response_header)
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
done:
free(buf);
@@ -389,6 +401,8 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
conn->response_header);
DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
free(conn->response_header);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
conn->response_header = NULL;
break;
case NTLMSTATE_TYPE2:
@@ -409,6 +423,8 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
authp->done = TRUE;
Curl_ntlm_wb_cleanup(conn);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
break;
case NTLMSTATE_TYPE3:
/* connection is already authenticated,
diff --git a/Utilities/cmcurl/lib/curl_path.c b/Utilities/cmcurl/lib/curl_path.c
index e843deac7..68f3e44ba 100644
--- a/Utilities/cmcurl/lib/curl_path.c
+++ b/Utilities/cmcurl/lib/curl_path.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
@@ -39,7 +39,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
char *working_path;
size_t working_path_len;
CURLcode result =
- Curl_urldecode(data, data->state.path, 0, &working_path,
+ Curl_urldecode(data, data->state.up.path, 0, &working_path,
&working_path_len, FALSE);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/curl_path.h b/Utilities/cmcurl/lib/curl_path.h
index 5ee4ff367..636c37f20 100644
--- a/Utilities/cmcurl/lib/curl_path.h
+++ b/Utilities/cmcurl/lib/curl_path.h
@@ -44,4 +44,4 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
char **path);
CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
-#endif
+#endif /* HEADER_CURL_PATH_H */
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index 97430647b..f09f2f332 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -37,9 +37,11 @@
/* The last #include file should be: */
#include "memdebug.h"
-#ifdef _WIN32
+#if defined(WIN32) && !defined(USE_LWIPSOCK)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
+#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
+#define SET_RCVTIMEO(tv,s) int tv = s*1000
#else
#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
#endif
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index e54e4875e..354bc5448 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -146,7 +146,6 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
const char *value, size_t len)
{
CURLcode result = CURLE_OK;
- unsigned int mechbit;
size_t mechlen;
if(!len)
@@ -160,7 +159,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
if(!strncmp(value, "*", len))
sasl->prefmech = SASL_AUTH_DEFAULT;
else {
- mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
+ unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
if(mechbit && mechlen == len)
sasl->prefmech |= mechbit;
else
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 7e6fd5e7e..5cdbc5923 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -44,6 +44,9 @@
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
+# ifndef NOGDI
+# define NOGDI
+# endif
#endif
/*
@@ -221,7 +224,7 @@
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
- * interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64,
+ * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
* performing this task will result in a synthesized IPv6 address.
*/
#ifdef __APPLE__
@@ -246,6 +249,7 @@
# if defined(_UNICODE) && !defined(UNICODE)
# define UNICODE
# endif
+# include <winerror.h>
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
@@ -659,7 +663,7 @@ int netware_init(void);
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
- defined(USE_DARWINSSL) || defined(USE_GSKIT)
+ defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
#define USE_SSL /* SSL support has been enabled */
#endif
@@ -815,4 +819,16 @@ endings either CRLF or LF so 't' is appropriate.
#define CURL_SA_FAMILY_T unsigned short
#endif
+/* Some convenience macros to get the larger/smaller value out of two given.
+ We prefix with CURL to prevent name collisions. */
+#define CURLMAX(x,y) ((x)>(y)?(x):(y))
+#define CURLMIN(x,y) ((x)<(y)?(x):(y))
+
+/* Some versions of the Android SDK is missing the declaration */
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
+struct passwd;
+int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
+ size_t buflen, struct passwd **result);
+#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 6d01ea156..413ccea91 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -515,4 +515,3 @@ typedef int sig_atomic_t;
#endif /* HEADER_CURL_SETUP_ONCE_H */
-
diff --git a/Utilities/cmcurl/lib/curl_sspi.c b/Utilities/cmcurl/lib/curl_sspi.c
index 11a7120a9..1d0de4ed3 100644
--- a/Utilities/cmcurl/lib/curl_sspi.c
+++ b/Utilities/cmcurl/lib/curl_sspi.c
@@ -90,8 +90,9 @@ CURLcode Curl_sspi_global_init(void)
return CURLE_FAILED_INIT;
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
- pInitSecurityInterface = (INITSECURITYINTERFACE_FN)
- GetProcAddress(s_hSecDll, SECURITYENTRYPOINT);
+ pInitSecurityInterface =
+ CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN,
+ (GetProcAddress(s_hSecDll, SECURITYENTRYPOINT)));
if(!pInitSecurityInterface)
return CURLE_FAILED_INIT;
@@ -131,7 +132,7 @@ void Curl_sspi_global_cleanup(void)
* Parameters:
*
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* identity [in/out] - The identity structure.
*
* Returns CURLE_OK on success.
diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c
index c1624a913..8e5937aa0 100644
--- a/Utilities/cmcurl/lib/curl_threads.c
+++ b/Utilities/cmcurl/lib/curl_threads.c
@@ -104,12 +104,21 @@ int Curl_thread_join(curl_thread_t *hnd)
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg)
{
+#ifdef _WIN32_WCE
+ typedef HANDLE curl_win_thread_handle_t;
+#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+ typedef unsigned long curl_win_thread_handle_t;
+#else
+ typedef uintptr_t curl_win_thread_handle_t;
+#endif
curl_thread_t t;
+ curl_win_thread_handle_t thread_handle;
#ifdef _WIN32_WCE
- t = CreateThread(NULL, 0, func, arg, 0, NULL);
+ thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL);
#else
- t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
+ thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);
#endif
+ t = (curl_thread_t)thread_handle;
if((t == 0) || (t == LongToHandle(-1L))) {
#ifdef _WIN32_WCE
DWORD gle = GetLastError();
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index 9e0d14a30..2a93644c5 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/lib/curl_threads.h
@@ -38,7 +38,8 @@
# define curl_thread_t HANDLE
# define curl_thread_t_null (HANDLE)0
# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
- (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
+ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
# define Curl_mutex_init(m) InitializeCriticalSection(m)
# else
# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
diff --git a/Utilities/cmcurl/lib/curlx.h b/Utilities/cmcurl/lib/curlx.h
index 6e418266b..4c77d4f2e 100644
--- a/Utilities/cmcurl/lib/curlx.h
+++ b/Utilities/cmcurl/lib/curlx.h
@@ -102,4 +102,3 @@
#endif /* ENABLE_CURLX_PRINTF */
#endif /* HEADER_CURL_CURLX_H */
-
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index 4fc85521d..78ef046d4 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.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
@@ -95,17 +95,17 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
{
char *newp = NULL;
char *dictp;
- char *ptr;
size_t len;
- char ch;
- int olen = 0;
CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
if(!newp || result)
return NULL;
- dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
+ dictp = malloc(len*2 + 1); /* add one for terminating zero */
if(dictp) {
+ char *ptr;
+ char ch;
+ int olen = 0;
/* According to RFC2229 section 2.2, these letters need to be escaped with
\[letter] */
for(ptr = newp;
@@ -136,7 +136,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- char *path = data->state.path;
+ char *path = data->state.up.path;
curl_off_t *bytecount = &data->req.bytecount;
*done = TRUE; /* unconditionally */
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
new file mode 100644
index 000000000..ef6013db9
--- /dev/null
+++ b/Utilities/cmcurl/lib/doh.c
@@ -0,0 +1,920 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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"
+#include "curl_addrinfo.h"
+#include "doh.h"
+
+#ifdef USE_NGHTTP2
+#include "sendf.h"
+#include "multiif.h"
+#include "url.h"
+#include "share.h"
+#include "curl_base64.h"
+#include "connect.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define DNS_CLASS_IN 0x01
+#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static const char * const errors[]={
+ "",
+ "Bad label",
+ "Out of range",
+ "Label loop",
+ "Too small",
+ "Out of memory",
+ "RDATA length",
+ "Malformat",
+ "Bad RCODE",
+ "Unexpected TYPE",
+ "Unexpected CLASS",
+ "No content",
+ "Bad ID"
+};
+
+static const char *doh_strerror(DOHcode code)
+{
+ if((code >= DOH_OK) && (code <= DOH_DNS_BAD_ID))
+ return errors[code];
+ return "bad error code";
+}
+#endif
+
+#ifdef DEBUGBUILD
+#define UNITTEST
+#else
+#define UNITTEST static
+#endif
+
+UNITTEST DOHcode doh_encode(const char *host,
+ DNStype dnstype,
+ unsigned char *dnsp, /* buffer */
+ size_t len, /* buffer size */
+ size_t *olen) /* output length */
+{
+ size_t hostlen = strlen(host);
+ unsigned char *orig = dnsp;
+ const char *hostp = host;
+
+ if(len < (12 + hostlen + 4))
+ return DOH_TOO_SMALL_BUFFER;
+
+ *dnsp++ = 0; /* 16 bit id */
+ *dnsp++ = 0;
+ *dnsp++ = 0x01; /* |QR| Opcode |AA|TC|RD| Set the RD bit */
+ *dnsp++ = '\0'; /* |RA| Z | RCODE | */
+ *dnsp++ = '\0';
+ *dnsp++ = 1; /* QDCOUNT (number of entries in the question section) */
+ *dnsp++ = '\0';
+ *dnsp++ = '\0'; /* ANCOUNT */
+ *dnsp++ = '\0';
+ *dnsp++ = '\0'; /* NSCOUNT */
+ *dnsp++ = '\0';
+ *dnsp++ = '\0'; /* ARCOUNT */
+
+ /* store a QNAME */
+ do {
+ char *dot = strchr(hostp, '.');
+ size_t labellen;
+ bool found = false;
+ if(dot) {
+ found = true;
+ labellen = dot - hostp;
+ }
+ else
+ labellen = strlen(hostp);
+ if(labellen > 63) {
+ /* too long label, error out */
+ *olen = 0;
+ return DOH_DNS_BAD_LABEL;
+ }
+ *dnsp++ = (unsigned char)labellen;
+ memcpy(dnsp, hostp, labellen);
+ dnsp += labellen;
+ hostp += labellen + 1;
+ if(!found) {
+ *dnsp++ = 0; /* terminating zero */
+ break;
+ }
+ } while(1);
+
+ *dnsp++ = '\0'; /* upper 8 bit TYPE */
+ *dnsp++ = (unsigned char)dnstype;
+ *dnsp++ = '\0'; /* upper 8 bit CLASS */
+ *dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */
+
+ *olen = dnsp - orig;
+ return DOH_OK;
+}
+
+static size_t
+doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize = size * nmemb;
+ struct dohresponse *mem = (struct dohresponse *)userp;
+
+ if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE)
+ /* suspiciously much for us */
+ return 0;
+
+ mem->memory = realloc(mem->memory, mem->size + realsize);
+ if(mem->memory == NULL)
+ /* out of memory! */
+ return 0;
+
+ memcpy(&(mem->memory[mem->size]), contents, realsize);
+ mem->size += realsize;
+
+ return realsize;
+}
+
+/* called from multi.c when this DOH transfer is complete */
+static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
+{
+ struct Curl_easy *data = doh->set.dohfor;
+ /* so one of the DOH request done for the 'data' transfer is now complete! */
+ data->req.doh.pending--;
+ infof(data, "a DOH request is completed, %d to go\n", data->req.doh.pending);
+ if(result)
+ infof(data, "DOH request %s\n", curl_easy_strerror(result));
+
+ if(!data->req.doh.pending) {
+ /* DOH completed */
+ curl_slist_free_all(data->req.doh.headers);
+ data->req.doh.headers = NULL;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+ return 0;
+}
+
+#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y); \
+ if(result) goto error
+
+static CURLcode dohprobe(struct Curl_easy *data,
+ struct dnsprobe *p, DNStype dnstype,
+ const char *host,
+ const char *url, CURLM *multi,
+ struct curl_slist *headers)
+{
+ struct Curl_easy *doh = NULL;
+ char *nurl = NULL;
+ CURLcode result = CURLE_OK;
+ timediff_t timeout_ms;
+ DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
+ &p->dohlen);
+ if(d) {
+ failf(data, "Failed to encode DOH packet [%d]\n", d);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ p->dnstype = dnstype;
+ p->serverdoh.memory = NULL;
+ /* the memory will be grown as needed by realloc in the doh_write_cb
+ function */
+ p->serverdoh.size = 0;
+
+ /* Note: this is code for sending the DoH request with GET but there's still
+ no logic that actually enables this. We should either add that ability or
+ yank out the GET code. Discuss! */
+ if(data->set.doh_get) {
+ char *b64;
+ size_t b64len;
+ result = Curl_base64url_encode(data, (char *)p->dohbuffer, p->dohlen,
+ &b64, &b64len);
+ if(result)
+ goto error;
+ nurl = aprintf("%s?dns=%s", url, b64);
+ free(b64);
+ if(!nurl) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ url = nurl;
+ }
+
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ /* Curl_open() is the internal version of curl_easy_init() */
+ result = Curl_open(&doh);
+ if(!result) {
+ /* pass in the struct pointer via a local variable to please coverity and
+ the gcc typecheck helpers */
+ struct dohresponse *resp = &p->serverdoh;
+ ERROR_CHECK_SETOPT(CURLOPT_URL, url);
+ ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
+ ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
+ if(!data->set.doh_get) {
+ ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer);
+ ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
+ }
+ ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+ ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+#ifndef CURLDEBUG
+ /* enforce HTTPS if not debug */
+ ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
+#endif
+ ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
+ ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+ doh->set.fmultidone = Curl_doh_done;
+ doh->set.dohfor = data; /* identify for which transfer this is done */
+ p->easy = doh;
+
+ /* add this transfer to the multi handle */
+ if(curl_multi_add_handle(multi, doh))
+ goto error;
+ }
+ else
+ goto error;
+ free(nurl);
+ return CURLE_OK;
+
+ error:
+ free(nurl);
+ Curl_close(doh);
+ return result;
+}
+
+/*
+ * Curl_doh() resolves a name using DOH. It resolves a name and returns a
+ * 'Curl_addrinfo *' with the address information.
+ */
+
+Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct Curl_easy *data = conn->data;
+ CURLcode result = CURLE_OK;
+ *waitp = TRUE; /* this never returns synchronously */
+ (void)conn;
+ (void)hostname;
+ (void)port;
+
+ /* start clean, consider allocating this struct on demand */
+ memset(&data->req.doh, 0, sizeof(struct dohdata));
+
+ data->req.doh.host = hostname;
+ data->req.doh.port = port;
+ data->req.doh.headers =
+ curl_slist_append(NULL,
+ "Content-Type: application/dns-message");
+ if(!data->req.doh.headers)
+ goto error;
+
+ if(conn->ip_version != CURL_IPRESOLVE_V6) {
+ /* create IPv4 DOH request */
+ result = dohprobe(data, &data->req.doh.probe[0], DNS_TYPE_A,
+ hostname, data->set.str[STRING_DOH],
+ data->multi, data->req.doh.headers);
+ if(result)
+ goto error;
+ data->req.doh.pending++;
+ }
+
+ if(conn->ip_version != CURL_IPRESOLVE_V4) {
+ /* create IPv6 DOH request */
+ result = dohprobe(data, &data->req.doh.probe[1], DNS_TYPE_AAAA,
+ hostname, data->set.str[STRING_DOH],
+ data->multi, data->req.doh.headers);
+ if(result)
+ goto error;
+ data->req.doh.pending++;
+ }
+ return NULL;
+
+ error:
+ curl_slist_free_all(data->req.doh.headers);
+ data->req.doh.headers = NULL;
+ curl_easy_cleanup(data->req.doh.probe[0].easy);
+ data->req.doh.probe[0].easy = NULL;
+ curl_easy_cleanup(data->req.doh.probe[1].easy);
+ data->req.doh.probe[1].easy = NULL;
+ return NULL;
+}
+
+static DOHcode skipqname(unsigned char *doh, size_t dohlen,
+ unsigned int *indexp)
+{
+ unsigned char length;
+ do {
+ if(dohlen < (*indexp + 1))
+ return DOH_DNS_OUT_OF_RANGE;
+ length = doh[*indexp];
+ if((length & 0xc0) == 0xc0) {
+ /* name pointer, advance over it and be done */
+ if(dohlen < (*indexp + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+ *indexp += 2;
+ break;
+ }
+ if(length & 0xc0)
+ return DOH_DNS_BAD_LABEL;
+ if(dohlen < (*indexp + 1 + length))
+ return DOH_DNS_OUT_OF_RANGE;
+ *indexp += 1 + length;
+ } while(length);
+ return DOH_OK;
+}
+
+static unsigned short get16bit(unsigned char *doh, int index)
+{
+ return (unsigned short)((doh[index] << 8) | doh[index + 1]);
+}
+
+static unsigned int get32bit(unsigned char *doh, int index)
+{
+ return (doh[index] << 24) | (doh[index + 1] << 16) |
+ (doh[index + 2] << 8) | doh[index + 3];
+}
+
+static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
+{
+ /* silently ignore addresses over the limit */
+ if(d->numaddr < DOH_MAX_ADDR) {
+ struct dohaddr *a = &d->addr[d->numaddr];
+ a->type = DNS_TYPE_A;
+ memcpy(&a->ip.v4, &doh[index], 4);
+ d->numaddr++;
+ }
+ return DOH_OK;
+}
+
+static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d)
+{
+ /* silently ignore addresses over the limit */
+ if(d->numaddr < DOH_MAX_ADDR) {
+ struct dohaddr *a = &d->addr[d->numaddr];
+ a->type = DNS_TYPE_AAAA;
+ memcpy(&a->ip.v6, &doh[index], 16);
+ d->numaddr++;
+ }
+ return DOH_OK;
+}
+
+static DOHcode cnameappend(struct cnamestore *c,
+ unsigned char *src,
+ size_t len)
+{
+ if(!c->alloc) {
+ c->allocsize = len + 1;
+ c->alloc = malloc(c->allocsize);
+ if(!c->alloc)
+ return DOH_OUT_OF_MEM;
+ }
+ else if(c->allocsize < (c->allocsize + len + 1)) {
+ char *ptr;
+ c->allocsize += len + 1;
+ ptr = realloc(c->alloc, c->allocsize);
+ if(!ptr) {
+ free(c->alloc);
+ return DOH_OUT_OF_MEM;
+ }
+ c->alloc = ptr;
+ }
+ memcpy(&c->alloc[c->len], src, len);
+ c->len += len;
+ c->alloc[c->len] = 0; /* keep it zero terminated */
+ return DOH_OK;
+}
+
+static DOHcode store_cname(unsigned char *doh,
+ size_t dohlen,
+ unsigned int index,
+ struct dohentry *d)
+{
+ struct cnamestore *c;
+ unsigned int loop = 128; /* a valid DNS name can never loop this much */
+ unsigned char length;
+
+ if(d->numcname == DOH_MAX_CNAME)
+ return DOH_OK; /* skip! */
+
+ c = &d->cname[d->numcname++];
+ do {
+ if(index >= dohlen)
+ return DOH_DNS_OUT_OF_RANGE;
+ length = doh[index];
+ if((length & 0xc0) == 0xc0) {
+ int newpos;
+ /* name pointer, get the new offset (14 bits) */
+ if((index + 1) >= dohlen)
+ return DOH_DNS_OUT_OF_RANGE;
+
+ /* move to the the new index */
+ newpos = (length & 0x3f) << 8 | doh[index + 1];
+ index = newpos;
+ continue;
+ }
+ else if(length & 0xc0)
+ return DOH_DNS_BAD_LABEL; /* bad input */
+ else
+ index++;
+
+ if(length) {
+ DOHcode rc;
+ if(c->len) {
+ rc = cnameappend(c, (unsigned char *)".", 1);
+ if(rc)
+ return rc;
+ }
+ if((index + length) > dohlen)
+ return DOH_DNS_BAD_LABEL;
+
+ rc = cnameappend(c, &doh[index], length);
+ if(rc)
+ return rc;
+ index += length;
+ }
+ } while(length && --loop);
+
+ if(!loop)
+ return DOH_DNS_LABEL_LOOP;
+ return DOH_OK;
+}
+
+static DOHcode rdata(unsigned char *doh,
+ size_t dohlen,
+ unsigned short rdlength,
+ unsigned short type,
+ int index,
+ struct dohentry *d)
+{
+ /* RDATA
+ - A (TYPE 1): 4 bytes
+ - AAAA (TYPE 28): 16 bytes
+ - NS (TYPE 2): N bytes */
+ DOHcode rc;
+
+ switch(type) {
+ case DNS_TYPE_A:
+ if(rdlength != 4)
+ return DOH_DNS_RDATA_LEN;
+ rc = store_a(doh, index, d);
+ if(rc)
+ return rc;
+ break;
+ case DNS_TYPE_AAAA:
+ if(rdlength != 16)
+ return DOH_DNS_RDATA_LEN;
+ rc = store_aaaa(doh, index, d);
+ if(rc)
+ return rc;
+ break;
+ case DNS_TYPE_CNAME:
+ rc = store_cname(doh, dohlen, index, d);
+ if(rc)
+ return rc;
+ break;
+ default:
+ /* unsupported type, just skip it */
+ break;
+ }
+ return DOH_OK;
+}
+
+static void init_dohentry(struct dohentry *de)
+{
+ memset(de, 0, sizeof(*de));
+ de->ttl = INT_MAX;
+}
+
+
+UNITTEST DOHcode doh_decode(unsigned char *doh,
+ size_t dohlen,
+ DNStype dnstype,
+ struct dohentry *d)
+{
+ unsigned char rcode;
+ unsigned short qdcount;
+ unsigned short ancount;
+ unsigned short type = 0;
+ unsigned short class;
+ unsigned short rdlength;
+ unsigned short nscount;
+ unsigned short arcount;
+ unsigned int index = 12;
+ DOHcode rc;
+
+ if(dohlen < 12)
+ return DOH_TOO_SMALL_BUFFER; /* too small */
+ if(doh[0] || doh[1])
+ return DOH_DNS_BAD_ID; /* bad ID */
+ rcode = doh[3] & 0x0f;
+ if(rcode)
+ return DOH_DNS_BAD_RCODE; /* bad rcode */
+
+ qdcount = get16bit(doh, 4);
+ while(qdcount) {
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+ if(dohlen < (index + 4))
+ return DOH_DNS_OUT_OF_RANGE;
+ index += 4; /* skip question's type and class */
+ qdcount--;
+ }
+
+ ancount = get16bit(doh, 6);
+ while(ancount) {
+ unsigned int ttl;
+
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ type = get16bit(doh, index);
+ if((type != DNS_TYPE_CNAME) && (type != dnstype))
+ /* Not the same type as was asked for nor CNAME */
+ return DOH_DNS_UNEXPECTED_TYPE;
+ index += 2;
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+ class = get16bit(doh, index);
+ if(DNS_CLASS_IN != class)
+ return DOH_DNS_UNEXPECTED_CLASS; /* unsupported */
+ index += 2;
+
+ if(dohlen < (index + 4))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ ttl = get32bit(doh, index);
+ if(ttl < d->ttl)
+ d->ttl = ttl;
+ index += 4;
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rdlength = get16bit(doh, index);
+ index += 2;
+ if(dohlen < (index + rdlength))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rc = rdata(doh, dohlen, rdlength, type, index, d);
+ if(rc)
+ return rc; /* bad rdata */
+ index += rdlength;
+ ancount--;
+ }
+
+ nscount = get16bit(doh, 8);
+ while(nscount) {
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+
+ if(dohlen < (index + 8))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ index += 2 + 2 + 4; /* type, class and ttl */
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rdlength = get16bit(doh, index);
+ index += 2;
+ if(dohlen < (index + rdlength))
+ return DOH_DNS_OUT_OF_RANGE;
+ index += rdlength;
+ nscount--;
+ }
+
+ arcount = get16bit(doh, 10);
+ while(arcount) {
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+
+ if(dohlen < (index + 8))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ index += 2 + 2 + 4; /* type, class and ttl */
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rdlength = get16bit(doh, index);
+ index += 2;
+ if(dohlen < (index + rdlength))
+ return DOH_DNS_OUT_OF_RANGE;
+ index += rdlength;
+ arcount--;
+ }
+
+ if(index != dohlen)
+ return DOH_DNS_MALFORMAT; /* something is wrong */
+
+ if((type != DNS_TYPE_NS) && !d->numcname && !d->numaddr)
+ /* nothing stored! */
+ return DOH_NO_CONTENT;
+
+ return DOH_OK; /* ok */
+}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void showdoh(struct Curl_easy *data,
+ struct dohentry *d)
+{
+ int i;
+ infof(data, "TTL: %u seconds\n", d->ttl);
+ for(i = 0; i < d->numaddr; i++) {
+ struct dohaddr *a = &d->addr[i];
+ if(a->type == DNS_TYPE_A) {
+ infof(data, "DOH A: %u.%u.%u.%u\n",
+ a->ip.v4[0], a->ip.v4[1],
+ a->ip.v4[2], a->ip.v4[3]);
+ }
+ else if(a->type == DNS_TYPE_AAAA) {
+ int j;
+ char buffer[128];
+ char *ptr;
+ size_t len;
+ snprintf(buffer, 128, "DOH AAAA: ");
+ ptr = &buffer[10];
+ len = 118;
+ for(j = 0; j < 16; j += 2) {
+ size_t l;
+ snprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+ d->addr[i].ip.v6[j + 1]);
+ l = strlen(ptr);
+ len -= l;
+ ptr += l;
+ }
+ infof(data, "%s\n", buffer);
+ }
+ }
+ for(i = 0; i < d->numcname; i++) {
+ infof(data, "CNAME: %s\n", d->cname[i].alloc);
+ }
+}
+#else
+#define showdoh(x,y)
+#endif
+
+/*
+ * doh2ai()
+ *
+ * This function returns a pointer to the first element of a newly allocated
+ * Curl_addrinfo struct linked list filled with the data from a set of DOH
+ * lookups. Curl_addrinfo is meant to work like the addrinfo struct does for
+ * a IPv6 stack, but usable also for IPv4, all hosts and environments.
+ *
+ * The memory allocated by this function *MUST* be free'd later on calling
+ * Curl_freeaddrinfo(). For each successful call to this function there
+ * must be an associated call later to Curl_freeaddrinfo().
+ */
+
+static Curl_addrinfo *
+doh2ai(const struct dohentry *de, const char *hostname, int port)
+{
+ Curl_addrinfo *ai;
+ Curl_addrinfo *prevai = NULL;
+ Curl_addrinfo *firstai = NULL;
+ struct sockaddr_in *addr;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *addr6;
+#endif
+ CURLcode result = CURLE_OK;
+ int i;
+
+ if(!de)
+ /* no input == no output! */
+ return NULL;
+
+ for(i = 0; i < de->numaddr; i++) {
+ size_t ss_size;
+ CURL_SA_FAMILY_T addrtype;
+ if(de->addr[i].type == DNS_TYPE_AAAA) {
+#ifndef ENABLE_IPV6
+ /* we can't handle IPv6 addresses */
+ continue;
+#else
+ ss_size = sizeof(struct sockaddr_in6);
+ addrtype = AF_INET6;
+#endif
+ }
+ else {
+ ss_size = sizeof(struct sockaddr_in);
+ addrtype = AF_INET;
+ }
+
+ ai = calloc(1, sizeof(Curl_addrinfo));
+ if(!ai) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ ai->ai_canonname = strdup(hostname);
+ if(!ai->ai_canonname) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai);
+ break;
+ }
+ ai->ai_addr = calloc(1, ss_size);
+ if(!ai->ai_addr) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai->ai_canonname);
+ free(ai);
+ break;
+ }
+
+ if(!firstai)
+ /* store the pointer we want to return from this function */
+ firstai = ai;
+
+ if(prevai)
+ /* make the previous entry point to this */
+ prevai->ai_next = ai;
+
+ ai->ai_family = addrtype;
+
+ /* we return all names as STREAM, so when using this address for TFTP
+ the type must be ignored and conn->socktype be used instead! */
+ ai->ai_socktype = SOCK_STREAM;
+
+ ai->ai_addrlen = (curl_socklen_t)ss_size;
+
+ /* leave the rest of the struct filled with zero */
+
+ switch(ai->ai_family) {
+ case AF_INET:
+ addr = (void *)ai->ai_addr; /* storage area for this info */
+ DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4));
+ memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr));
+ addr->sin_family = (CURL_SA_FAMILY_T)addrtype;
+ addr->sin_port = htons((unsigned short)port);
+ break;
+
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ addr6 = (void *)ai->ai_addr; /* storage area for this info */
+ DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
+ memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr));
+ addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype;
+ addr6->sin6_port = htons((unsigned short)port);
+ break;
+#endif
+ }
+
+ prevai = ai;
+ }
+
+ if(result) {
+ Curl_freeaddrinfo(firstai);
+ firstai = NULL;
+ }
+
+ return firstai;
+}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static const char *type2name(DNStype dnstype)
+{
+ return (dnstype == DNS_TYPE_A)?"A":"AAAA";
+}
+#endif
+
+UNITTEST void de_cleanup(struct dohentry *d)
+{
+ int i = 0;
+ for(i = 0; i < d->numcname; i++) {
+ free(d->cname[i].alloc);
+ }
+}
+
+CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dnsp)
+{
+ struct Curl_easy *data = conn->data;
+ *dnsp = NULL; /* defaults to no response */
+
+ if(!data->req.doh.probe[0].easy && !data->req.doh.probe[1].easy) {
+ failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
+ return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else if(!data->req.doh.pending) {
+ DOHcode rc;
+ DOHcode rc2;
+ struct dohentry de;
+ struct Curl_dns_entry *dns;
+ struct Curl_addrinfo *ai;
+ /* remove DOH handles from multi handle and close them */
+ curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
+ Curl_close(data->req.doh.probe[0].easy);
+ curl_multi_remove_handle(data->multi, data->req.doh.probe[1].easy);
+ Curl_close(data->req.doh.probe[1].easy);
+
+ /* parse the responses, create the struct and return it! */
+ init_dohentry(&de);
+ rc = doh_decode(data->req.doh.probe[0].serverdoh.memory,
+ data->req.doh.probe[0].serverdoh.size,
+ data->req.doh.probe[0].dnstype,
+ &de);
+ free(data->req.doh.probe[0].serverdoh.memory);
+ if(rc) {
+ infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc),
+ type2name(data->req.doh.probe[0].dnstype),
+ data->req.doh.host);
+ }
+ rc2 = doh_decode(data->req.doh.probe[1].serverdoh.memory,
+ data->req.doh.probe[1].serverdoh.size,
+ data->req.doh.probe[1].dnstype,
+ &de);
+ free(data->req.doh.probe[1].serverdoh.memory);
+ if(rc2) {
+ infof(data, "DOG: %s type %s for %s\n", doh_strerror(rc2),
+ type2name(data->req.doh.probe[1].dnstype),
+ data->req.doh.host);
+ }
+ if(!rc || !rc2) {
+ infof(data, "DOH Host name: %s\n", data->req.doh.host);
+ showdoh(data, &de);
+
+ ai = doh2ai(&de, data->req.doh.host, data->req.doh.port);
+ if(!ai) {
+ de_cleanup(&de);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* we got a response, store it in the cache */
+ dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ de_cleanup(&de);
+ if(!dns)
+ /* returned failure, bail out nicely */
+ Curl_freeaddrinfo(ai);
+ else {
+ conn->async.dns = dns;
+ *dnsp = dns;
+ return CURLE_OK;
+ }
+ }
+ de_cleanup(&de);
+
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ return CURLE_OK;
+}
+
+#else /* !USE_NGHTTP2 */
+/*
+ */
+Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ (void)conn;
+ (void)hostname;
+ (void)port;
+ (void)waitp;
+ return NULL;
+}
+
+CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dnsp)
+{
+ (void)conn;
+ (void)dnsp;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* USE_NGHTTP2 */
diff --git a/Utilities/cmcurl/lib/doh.h b/Utilities/cmcurl/lib/doh.h
new file mode 100644
index 000000000..83c79bc5d
--- /dev/null
+++ b/Utilities/cmcurl/lib/doh.h
@@ -0,0 +1,105 @@
+#ifndef HEADER_CURL_DOH_H
+#define HEADER_CURL_DOH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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 "urldata.h"
+#include "curl_addrinfo.h"
+
+/*
+ * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
+ * and returns a 'Curl_addrinfo *' with the address information.
+ */
+
+Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dns);
+
+int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+
+typedef enum {
+ DOH_OK,
+ DOH_DNS_BAD_LABEL, /* 1 */
+ DOH_DNS_OUT_OF_RANGE, /* 2 */
+ DOH_DNS_LABEL_LOOP, /* 3 */
+ DOH_TOO_SMALL_BUFFER, /* 4 */
+ DOH_OUT_OF_MEM, /* 5 */
+ DOH_DNS_RDATA_LEN, /* 6 */
+ DOH_DNS_MALFORMAT, /* 7 */
+ DOH_DNS_BAD_RCODE, /* 8 - no such name */
+ DOH_DNS_UNEXPECTED_TYPE, /* 9 */
+ DOH_DNS_UNEXPECTED_CLASS, /* 10 */
+ DOH_NO_CONTENT, /* 11 */
+ DOH_DNS_BAD_ID /* 12 */
+} DOHcode;
+
+typedef enum {
+ DNS_TYPE_A = 1,
+ DNS_TYPE_NS = 2,
+ DNS_TYPE_CNAME = 5,
+ DNS_TYPE_AAAA = 28
+} DNStype;
+
+#define DOH_MAX_ADDR 24
+#define DOH_MAX_CNAME 4
+
+struct cnamestore {
+ size_t len; /* length of cname */
+ char *alloc; /* allocated pointer */
+ size_t allocsize; /* allocated size */
+};
+
+struct dohaddr {
+ int type;
+ union {
+ unsigned char v4[4]; /* network byte order */
+ unsigned char v6[16];
+ } ip;
+};
+
+struct dohentry {
+ unsigned int ttl;
+ int numaddr;
+ struct dohaddr addr[DOH_MAX_ADDR];
+ int numcname;
+ struct cnamestore cname[DOH_MAX_CNAME];
+};
+
+
+#ifdef DEBUGBUILD
+DOHcode doh_encode(const char *host,
+ DNStype dnstype,
+ unsigned char *dnsp, /* buffer */
+ size_t len, /* buffer size */
+ size_t *olen); /* output length */
+DOHcode doh_decode(unsigned char *doh,
+ size_t dohlen,
+ DNStype dnstype,
+ struct dohentry *d);
+void de_cleanup(struct dohentry *d);
+#endif
+#endif /* HEADER_CURL_DOH_H */
diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c
index cbb308d78..2c6177aea 100644
--- a/Utilities/cmcurl/lib/dotdot.c
+++ b/Utilities/cmcurl/lib/dotdot.c
@@ -62,6 +62,8 @@ char *Curl_dedotdotify(const char *input)
if(!out)
return NULL; /* out of memory */
+ *out = 0; /* zero terminates, for inputs like "./" */
+
/* get a cloned copy of the input */
clone = strdup(input);
if(!clone) {
diff --git a/Utilities/cmcurl/lib/dotdot.h b/Utilities/cmcurl/lib/dotdot.h
index fac8e6f2a..125af4367 100644
--- a/Utilities/cmcurl/lib/dotdot.h
+++ b/Utilities/cmcurl/lib/dotdot.h
@@ -22,4 +22,4 @@
*
***************************************************************************/
char *Curl_dedotdotify(const char *input);
-#endif
+#endif /* HEADER_CURL_DOTDOT_H */
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index 6b914353d..4de4e6522 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -113,7 +113,7 @@ static CURLcode win32_init(void)
res = WSAStartup(wVersionRequested, &wsaData);
if(res != 0)
- /* Tell the user that we couldn't find a useable */
+ /* Tell the user that we couldn't find a usable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
@@ -125,7 +125,7 @@ static CURLcode win32_init(void)
if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
- /* Tell the user that we couldn't find a useable */
+ /* Tell the user that we couldn't find a usable */
/* winsock.dll. */
WSACleanup();
@@ -661,38 +661,27 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
bool done = FALSE;
CURLMcode mcode = CURLM_OK;
CURLcode result = CURLE_OK;
- struct curltime before;
- int without_fds = 0; /* count number of consecutive returns from
- curl_multi_wait() without any filedescriptors */
while(!done && !mcode) {
int still_running = 0;
int rc;
- before = Curl_now();
mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
if(!mcode) {
if(!rc) {
- struct curltime after = Curl_now();
+ long sleep_ms;
/* If it returns without any filedescriptor instantly, we need to
avoid busy-looping during periods where it has nothing particular
to wait for */
- if(Curl_timediff(after, before) <= 10) {
- without_fds++;
- if(without_fds > 2) {
- int sleep_ms = without_fds < 10 ? (1 << (without_fds - 1)) : 1000;
- Curl_wait_ms(sleep_ms);
- }
+ curl_multi_timeout(multi, &sleep_ms);
+ if(sleep_ms) {
+ if(sleep_ms > 1000)
+ sleep_ms = 1000;
+ Curl_wait_ms((int)sleep_ms);
}
- else
- /* it wasn't "instant", restart counter */
- without_fds = 0;
}
- else
- /* got file descriptor, restart counter */
- without_fds = 0;
mcode = curl_multi_perform(multi, &still_running);
}
@@ -969,6 +958,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->change.referer_alloc = TRUE;
}
+ /* Reinitialize an SSL engine for the new handle
+ * note: the engine name has already been copied by dupset */
+ if(outcurl->set.str[STRING_SSL_ENGINE]) {
+ if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
+ goto fail;
+ }
+
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(&outcurl->state.resolver,
data->state.resolver))
@@ -1006,10 +1002,6 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
*/
void curl_easy_reset(struct Curl_easy *data)
{
- Curl_safefree(data->state.pathbuffer);
-
- data->state.path = NULL;
-
Curl_free_request_state(data);
/* zero out UserDefined data: */
@@ -1201,3 +1193,22 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
return result;
}
+
+/*
+ * Performs connection upkeep for the given session handle.
+ */
+CURLcode curl_easy_upkeep(struct Curl_easy *data)
+{
+ /* Verify that we got an easy handle we can work with. */
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(data->multi_easy) {
+ /* Use the common function to keep connections alive. */
+ return Curl_upkeep(&data->multi_easy->conn_cache, data);
+ }
+ else {
+ /* No connections, so just return success */
+ return CURLE_OK;
+ }
+}
diff --git a/Utilities/cmcurl/lib/easyif.h b/Utilities/cmcurl/lib/easyif.h
index f6132cc70..6ba7e549d 100644
--- a/Utilities/cmcurl/lib/easyif.h
+++ b/Utilities/cmcurl/lib/easyif.h
@@ -30,4 +30,3 @@ CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy);
#endif
#endif /* HEADER_CURL_EASYIF_H */
-
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index b7e2d32a6..afd3899f9 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/lib/escape.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,7 +41,7 @@
its behavior is altered by the current locale.
See https://tools.ietf.org/html/rfc3986#section-2.3
*/
-static bool Curl_isunreserved(unsigned char in)
+bool Curl_isunreserved(unsigned char in)
{
switch(in) {
case '0': case '1': case '2': case '3': case '4':
@@ -82,7 +82,6 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
size_t alloc;
char *ns;
char *testing_ptr = NULL;
- unsigned char in; /* we need to treat the characters unsigned */
size_t newlen;
size_t strindex = 0;
size_t length;
@@ -100,7 +99,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
length = alloc-1;
while(length--) {
- in = *string;
+ unsigned char in = *string; /* we need to treat the characters unsigned */
if(Curl_isunreserved(in))
/* just copy this */
@@ -142,6 +141,8 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
* Returns a pointer to a malloced string in *ostring with length given in
* *olen. If length == 0, the length is assumed to be strlen(string).
*
+ * 'data' can be set to NULL but then this function can't convert network
+ * data to host for non-ascii.
*/
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
@@ -150,16 +151,15 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
{
size_t alloc = (length?length:strlen(string)) + 1;
char *ns = malloc(alloc);
- unsigned char in;
size_t strindex = 0;
unsigned long hex;
- CURLcode result;
+ CURLcode result = CURLE_OK;
if(!ns)
return CURLE_OUT_OF_MEMORY;
while(--alloc > 0) {
- in = *string;
+ unsigned char in = *string;
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
@@ -173,11 +173,13 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
- result = Curl_convert_from_network(data, (char *)&in, 1);
- if(result) {
- /* Curl_convert_from_network calls failf if unsuccessful */
- free(ns);
- return result;
+ if(data) {
+ result = Curl_convert_from_network(data, (char *)&in, 1);
+ if(result) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(ns);
+ return result;
+ }
}
string += 2;
diff --git a/Utilities/cmcurl/lib/escape.h b/Utilities/cmcurl/lib/escape.h
index 638666f03..d8bbe5cb0 100644
--- a/Utilities/cmcurl/lib/escape.h
+++ b/Utilities/cmcurl/lib/escape.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, 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
@@ -24,10 +24,10 @@
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
+bool Curl_isunreserved(unsigned char in);
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
char **ostring, size_t *olen,
bool reject_crlf);
#endif /* HEADER_CURL_ESCAPE_H */
-
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index db04cc2da..722b55e9d 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -143,7 +143,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
#endif
size_t real_path_len;
- CURLcode result = Curl_urldecode(data, data->state.path, 0, &real_path,
+ CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
&real_path_len, FALSE);
if(result)
return result;
@@ -197,7 +197,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
file->fd = fd;
if(!data->set.upload && (fd == -1)) {
- failf(data, "Couldn't open file %s", data->state.path);
+ failf(data, "Couldn't open file %s", data->state.up.path);
file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE;
}
@@ -256,8 +256,6 @@ static CURLcode file_upload(struct connectdata *conn)
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
- size_t nread;
- size_t nwrite;
curl_off_t bytecount = 0;
struct_stat file_stat;
const char *buf2;
@@ -306,15 +304,17 @@ static CURLcode file_upload(struct connectdata *conn)
}
while(!result) {
- int readcount;
- result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount);
+ size_t nread;
+ size_t nwrite;
+ size_t readcount;
+ result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount);
if(result)
break;
if(readcount <= 0) /* fix questionable compare error. curlvms */
break;
- nread = (size_t)readcount;
+ nread = readcount;
/*skip bytes before resume point*/
if(data->state.resume_from) {
@@ -378,7 +378,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
curl_off_t expected_size = 0;
bool size_known;
bool fstated = FALSE;
- ssize_t nread;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
@@ -387,7 +386,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
*done = TRUE; /* unconditionally */
- Curl_initinfo(data);
Curl_pgrsStartNow(data);
if(data->set.upload)
@@ -414,21 +412,18 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
}
}
- /* If we have selected NOBODY and HEADER, it means that we only want file
- information. Which for FILE can't be much more than the file size and
- date. */
- if(data->set.opt_no_body && data->set.include_header && fstated) {
+ if(fstated) {
time_t filetime;
struct tm buffer;
const struct tm *tm = &buffer;
char header[80];
snprintf(header, sizeof(header),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0);
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
if(result)
return result;
- result = Curl_client_write(conn, CLIENTWRITE_BOTH,
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
(char *)"Accept-ranges: bytes\r\n", 0);
if(result)
return result;
@@ -440,19 +435,22 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
snprintf(header, sizeof(header),
- "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
Curl_month[tm->tm_mon],
tm->tm_year + 1900,
tm->tm_hour,
tm->tm_min,
- tm->tm_sec);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0);
- if(!result)
- /* set the file size to make it available post transfer */
- Curl_pgrsSetDownloadSize(data, expected_size);
- return result;
+ tm->tm_sec,
+ data->set.opt_no_body ? "": "\r\n");
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
+ if(result)
+ return result;
+ /* set the file size to make it available post transfer */
+ Curl_pgrsSetDownloadSize(data, expected_size);
+ if(data->set.opt_no_body)
+ return result;
}
/* Check whether file range has been specified */
@@ -461,7 +459,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
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 */
+ * of the stream if the filesize could be determined */
if(data->state.resume_from < 0) {
if(!fstated) {
failf(data, "Can't get the size of file.");
@@ -502,6 +500,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
while(!result) {
+ ssize_t nread;
/* Don't fill a whole buffer if we want less than all data */
size_t bytestoread;
diff --git a/Utilities/cmcurl/lib/file.h b/Utilities/cmcurl/lib/file.h
index c12ae0e09..20828ad4a 100644
--- a/Utilities/cmcurl/lib/file.h
+++ b/Utilities/cmcurl/lib/file.h
@@ -38,4 +38,3 @@ extern const struct Curl_handler Curl_handler_file;
#endif
#endif /* HEADER_CURL_FILE_H */
-
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index f91241052..202d930c7 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -39,16 +39,13 @@
#include "sendf.h"
#include "strdup.h"
#include "rand.h"
+#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-/* What kind of Content-Type to use on un-specified files with unrecognized
- extensions. */
-#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
-
#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
@@ -305,7 +302,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
* Set the contents property.
*/
case CURLFORM_PTRCONTENTS:
- current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
+ current_form->flags |= HTTPPOST_PTRCONTENTS;
+ /* FALLTHROUGH */
case CURLFORM_COPYCONTENTS:
if(current_form->value)
return_value = CURL_FORMADD_OPTION_TWICE;
@@ -725,7 +723,7 @@ int curl_formget(struct curl_httppost *form, void *arg,
while(!result) {
char buffer[8192];
- size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
+ size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart);
if(!nread)
break;
@@ -812,7 +810,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
curl_mime *form = NULL;
- curl_mime *multipart;
curl_mimepart *part;
struct curl_httppost *file;
@@ -831,7 +828,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
/* Process each top part. */
for(; !result && post; post = post->next) {
/* If we have more than a file here, create a mime subpart and fill it. */
- multipart = form;
+ curl_mime *multipart = form;
if(post->more) {
part = curl_mime_addpart(form);
if(!part)
@@ -883,7 +880,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
compatibility: use of "-" pseudo file name should be avoided. */
result = curl_mime_data_cb(part, (curl_off_t) -1,
(curl_read_callback) fread,
- (curl_seek_callback) fseek,
+ CURLX_FUNCTION_CAST(curl_seek_callback,
+ fseek),
NULL, (void *) stdin);
}
else
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index a42c0c7c6..ce889ab29 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -239,8 +239,8 @@ static void close_secondarysocket(struct connectdata *conn)
static void freedirs(struct ftp_conn *ftpc)
{
- int i;
if(ftpc->dirs) {
+ int i;
for(i = 0; i < ftpc->dirdepth; i++) {
free(ftpc->dirs[i]);
ftpc->dirs[i] = NULL;
@@ -637,8 +637,6 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* line in a response or continue reading. */
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- time_t timeout; /* timeout in milliseconds */
- time_t interval_ms;
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -657,7 +655,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
- timeout = Curl_pp_state_timeout(pp);
+ time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
+ time_t interval_ms;
if(timeout <= 0) {
failf(data, "FTP response timeout");
@@ -1445,6 +1444,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
+ struct FTP *ftp = data->req.protop;
/* If this output is to be machine-parsed, the NLST command might be better
to use, since the LIST command output is not specified or standard in any
@@ -1461,7 +1461,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
then just do LIST (in that case: nothing to do here)
*/
char *cmd, *lstArg, *slashPos;
- const char *inpath = data->state.path;
+ const char *inpath = ftp->path;
lstArg = NULL;
if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
@@ -1589,7 +1589,6 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
struct FTP *ftp = conn->data->req.protop;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- int seekerr = CURL_SEEKFUNC_OK;
if((data->state.resume_from && !sizechecked) ||
((data->state.resume_from > 0) && sizechecked)) {
@@ -1605,6 +1604,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* 3. pass file-size number of bytes in the source file */
/* 4. lower the infilesize counter */
/* => transfer as usual */
+ int seekerr = CURL_SEEKFUNC_OK;
if(data->state.resume_from < 0) {
/* Got no given size to start from, figure it out */
@@ -2782,7 +2782,6 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
char *ptr = &data->state.buffer[4]; /* start on the first letter */
const size_t buf_size = data->set.buffer_size;
char *dir;
- char *store;
bool entry_extracted = FALSE;
dir = malloc(nread + 1);
@@ -2805,6 +2804,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if('\"' == *ptr) {
/* it started good */
+ char *store;
ptr++;
for(store = dir; *ptr;) {
if('\"' == *ptr) {
@@ -3142,7 +3142,6 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
int ftpcode;
CURLcode result = CURLE_OK;
char *path = NULL;
- const char *path_to_use = data->state.path;
if(!ftp)
return CURLE_OK;
@@ -3194,7 +3193,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(!result)
/* get the "raw" path */
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE);
+ result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
@@ -3214,9 +3213,11 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
ftpc->prevpath[dlen] = 0; /* terminate */
}
else {
+ free(path);
/* we never changed dir */
ftpc->prevpath = strdup("");
- free(path);
+ if(!ftpc->prevpath)
+ return CURLE_OUT_OF_MEMORY;
}
if(ftpc->prevpath)
infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
@@ -3347,7 +3348,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
/* Send any post-transfer QUOTE strings? */
if(!status && !result && !premature && data->set.postquote)
result = ftp_sendquote(conn, data->set.postquote);
-
+ Curl_safefree(ftp->pathalloc);
return result;
}
@@ -3697,12 +3698,13 @@ static void wc_data_dtor(void *ptr)
static CURLcode init_wc_data(struct connectdata *conn)
{
char *last_slash;
- char *path = conn->data->state.path;
+ struct FTP *ftp = conn->data->req.protop;
+ char *path = ftp->path;
struct WildcardData *wildcard = &(conn->data->wildcard);
CURLcode result = CURLE_OK;
struct ftp_wc *ftpwc = NULL;
- last_slash = strrchr(conn->data->state.path, '/');
+ last_slash = strrchr(ftp->path, '/');
if(last_slash) {
last_slash++;
if(last_slash[0] == '\0') {
@@ -3759,7 +3761,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
goto fail;
}
- wildcard->path = strdup(conn->data->state.path);
+ wildcard->path = strdup(ftp->path);
if(!wildcard->path) {
result = CURLE_OUT_OF_MEMORY;
goto fail;
@@ -3830,16 +3832,15 @@ static CURLcode wc_statemach(struct connectdata *conn)
/* filelist has at least one file, lets get first one */
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
+ struct FTP *ftp = conn->data->req.protop;
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
if(!tmp_path)
return CURLE_OUT_OF_MEMORY;
- /* switch default "state.pathbuffer" and tmp_path, good to see
- ftp_parse_url_path function to understand this trick */
- Curl_safefree(conn->data->state.pathbuffer);
- conn->data->state.pathbuffer = tmp_path;
- conn->data->state.path = tmp_path;
+ /* switch default ftp->path and tmp_path */
+ free(ftp->pathalloc);
+ ftp->pathalloc = ftp->path = tmp_path;
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) {
@@ -3965,10 +3966,14 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
enum protection_level data_sec = conn->data_prot;
#endif
+ if(!cmd)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
write_len = strlen(cmd);
- if(write_len > (sizeof(s) -3))
+ if(!write_len || write_len > (sizeof(s) -3))
return CURLE_BAD_FUNCTION_ARGUMENT;
+ memcpy(&s, cmd, write_len);
strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
write_len += 2;
bytes_written = 0;
@@ -3993,8 +3998,7 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
break;
if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT,
- sptr, (size_t)bytes_written, conn);
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
if(bytes_written != (ssize_t)write_len) {
write_len -= bytes_written;
@@ -4104,7 +4108,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
const char *slash_pos; /* position of the first '/' char in curpos */
- const char *path_to_use = data->state.path;
+ const char *path_to_use = ftp->path;
const char *cur_pos;
const char *filename = NULL;
@@ -4190,7 +4194,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
/* parse the URL path into separate path components */
while((slash_pos = strchr(cur_pos, '/')) != NULL) {
/* 1 or 0 pointer offset to indicate absolute directory */
- ssize_t absolute_dir = ((cur_pos - data->state.path > 0) &&
+ ssize_t absolute_dir = ((cur_pos - ftp->path > 0) &&
(ftpc->dirdepth == 0))?1:0;
/* seek out the next path component */
@@ -4267,7 +4271,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, TRUE);
+ Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE);
if(result) {
freedirs(ftpc);
return result;
@@ -4385,24 +4389,24 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
{
struct Curl_easy *data = conn->data;
char *type;
- char command;
struct FTP *ftp;
- conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
+ conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1);
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
- data->state.path++; /* don't include the initial slash */
+ ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
data->state.slash_removed = TRUE; /* we've skipped the slash */
/* FTP URLs support an extension like ";type=<typecode>" that
* we'll try to get now! */
- type = strstr(data->state.path, ";type=");
+ type = strstr(ftp->path, ";type=");
if(!type)
type = strstr(conn->host.rawalloc, ";type=");
if(type) {
+ char command;
*type = 0; /* it was in the middle of the hostname */
command = Curl_raw_toupper(type[6]);
conn->bits.type_set = TRUE;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index 7ec339118..38d03223c 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -105,6 +105,8 @@ struct FTP {
curl_off_t *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
+ char *path; /* points to the urlpieces struct field */
+ char *pathalloc; /* if non-NULL a pointer to an allocated path */
/* transfer a file/body or not, done as a typedefed enum just to make
debuggers display the full symbol and not just the numerical value */
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index d280eebfa..54c2c2f1c 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -85,7 +85,6 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
#ifdef USE_SSL
Curl_ssl_free_certinfo(data);
#endif
-
return CURLE_OK;
}
@@ -281,6 +280,28 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
*param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
data->progress.size_ul:-1;
break;
+ case CURLINFO_TOTAL_TIME_T:
+ *param_offt = data->progress.timespent;
+ break;
+ case CURLINFO_NAMELOOKUP_TIME_T:
+ *param_offt = data->progress.t_nslookup;
+ break;
+ case CURLINFO_CONNECT_TIME_T:
+ *param_offt = data->progress.t_connect;
+ break;
+ case CURLINFO_APPCONNECT_TIME_T:
+ *param_offt = data->progress.t_appconnect;
+ break;
+ case CURLINFO_PRETRANSFER_TIME_T:
+ *param_offt = data->progress.t_pretransfer;
+ break;
+ case CURLINFO_STARTTRANSFER_TIME_T:
+ *param_offt = data->progress.t_starttransfer;
+ break;
+ case CURLINFO_REDIRECT_TIME_T:
+ *param_offt = data->progress.t_redirect;
+ break;
+
default:
return CURLE_UNKNOWN_OPTION;
}
diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c
index b7c31b695..b441a641d 100644
--- a/Utilities/cmcurl/lib/gopher.c
+++ b/Utilities/cmcurl/lib/gopher.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
@@ -78,7 +78,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
curl_off_t *bytecount = &data->req.bytecount;
- char *path = data->state.path;
+ char *path = data->state.up.path;
char *sel = NULL;
char *sel_org = NULL;
ssize_t amount, k;
@@ -89,22 +89,15 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
/* Create selector. Degenerate cases: / and /1 => convert to "" */
if(strlen(path) <= 2) {
sel = (char *)"";
- len = (int)strlen(sel);
+ len = strlen(sel);
}
else {
char *newp;
- size_t j, i;
/* Otherwise, drop / and the first character (i.e., item type) ... */
newp = path;
newp += 2;
- /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
- j = strlen(newp);
- for(i = 0; i<j; i++)
- if(newp[i] == '?')
- newp[i] = '\x09';
-
/* ... and finally unescape */
result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
if(result)
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 15a128fec..421d68f76 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -60,8 +60,6 @@ Curl_hash_init(struct curl_hash *h,
comp_function comparator,
curl_hash_dtor dtor)
{
- int i;
-
if(!slots || !hfunc || !comparator ||!dtor) {
return 1; /* failure */
}
@@ -74,6 +72,7 @@ Curl_hash_init(struct curl_hash *h,
h->table = malloc(slots * sizeof(struct curl_llist));
if(h->table) {
+ int i;
for(i = 0; i < slots; ++i)
Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor);
return 0; /* fine */
@@ -140,11 +139,10 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
{
struct curl_llist_element *le;
- struct curl_hash_element *he;
struct curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- he = le->ptr;
+ struct curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
--h->size;
@@ -162,13 +160,12 @@ void *
Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
{
struct curl_llist_element *le;
- struct curl_hash_element *he;
struct curl_llist *l;
if(h) {
l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- he = le->ptr;
+ struct curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
return he->ptr;
}
@@ -291,7 +288,6 @@ void Curl_hash_start_iterate(struct curl_hash *hash,
struct curl_hash_element *
Curl_hash_next_element(struct curl_hash_iterator *iter)
{
- int i;
struct curl_hash *h = iter->hash;
/* Get the next element in the current list, if any */
@@ -300,6 +296,7 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
/* If we have reached the end of the list, find the next one */
if(!iter->current_element) {
+ int i;
for(i = iter->slot_index; i < h->slots; i++) {
if(h->table[i].head) {
iter->current_element = h->table[i].head;
diff --git a/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c
index dae95054b..bf49ebec5 100644
--- a/Utilities/cmcurl/lib/hmac.c
+++ b/Utilities/cmcurl/lib/hmac.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
@@ -58,7 +58,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
unsigned char b;
/* Create HMAC context. */
- i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize +
+ i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize +
hashparams->hmac_resultlen;
ctxt = malloc(i);
diff --git a/Utilities/cmcurl/lib/hostasyn.c b/Utilities/cmcurl/lib/hostasyn.c
index 7b6e8568a..6ff60ba61 100644
--- a/Utilities/cmcurl/lib/hostasyn.c
+++ b/Utilities/cmcurl/lib/hostasyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, 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
@@ -111,31 +111,6 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
return result;
}
-/* Call this function after Curl_connect() has returned async=TRUE and
- then a successful name resolve has been received.
-
- Note: this function disconnects and frees the conn data in case of
- resolve failure */
-CURLcode Curl_async_resolved(struct connectdata *conn,
- bool *protocol_done)
-{
- CURLcode result;
-
- if(conn->async.dns) {
- conn->dns_entry = conn->async.dns;
- conn->async.dns = NULL;
- }
-
- result = Curl_setup_conn(conn, protocol_done);
-
- if(result)
- /* We're not allowed to return failure with memory left allocated
- in the connectdata struct, free those here */
- Curl_disconnect(conn, FALSE); /* close the connection */
-
- return result;
-}
-
/*
* Curl_getaddrinfo() is the generic low-level name resolve API within this
* source file. There are several versions of this function - for different
diff --git a/Utilities/cmcurl/lib/hostcheck.h b/Utilities/cmcurl/lib/hostcheck.h
index 86e3b96a9..f562df9ae 100644
--- a/Utilities/cmcurl/lib/hostcheck.h
+++ b/Utilities/cmcurl/lib/hostcheck.h
@@ -29,4 +29,3 @@
int Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
#endif /* HEADER_CURL_HOSTCHECK_H */
-
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index c2f9defd9..f589a0b2c 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -60,6 +60,7 @@
#include "url.h"
#include "inet_ntop.h"
#include "multiif.h"
+#include "doh.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -454,7 +455,7 @@ Curl_cache_addr(struct Curl_easy *data,
/* shuffle addresses if requested */
if(data->set.dns_shuffle_addresses) {
CURLcode result = Curl_shuffle_addr(data, &addr);
- if(!result)
+ if(result)
return NULL;
}
@@ -565,23 +566,27 @@ int Curl_resolv(struct connectdata *conn,
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 */
- addr = Curl_getaddrinfo(conn,
+ if(data->set.doh) {
+ addr = Curl_doh(conn, hostname, port, &respwait);
+ }
+ else {
+ /* 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 */
+ addr = Curl_getaddrinfo(conn,
#ifdef DEBUGBUILD
- (data->set.str[STRING_DEVICE]
- && !strcmp(data->set.str[STRING_DEVICE],
- "LocalHost"))?"localhost":
+ (data->set.str[STRING_DEVICE]
+ && !strcmp(data->set.str[STRING_DEVICE],
+ "LocalHost"))?"localhost":
#endif
- hostname, port, &respwait);
-
+ hostname, port, &respwait);
+ }
if(!addr) {
if(respwait) {
/* the response to our resolve call will come asynchronously at
a later time, good or bad */
/* First, check that we haven't received the info by now */
- result = Curl_resolver_is_resolved(conn, &dns);
+ result = Curl_resolv_check(conn, &dns);
if(result) /* error detected */
return CURLRESOLV_ERROR;
if(dns)
@@ -907,7 +912,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
char *entry_id;
size_t entry_len;
char address[64];
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char *addresses = NULL;
+#endif
char *addr_begin;
char *addr_end;
char *port_ptr;
@@ -930,7 +937,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
goto err;
port = (int)tmp_port;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
addresses = end_ptr + 1;
+#endif
while(*end_ptr) {
size_t alen;
@@ -1010,24 +1019,28 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
/* See if its already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+ if(dns) {
+ infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
+ hostname, port);
+ /* delete old entry entry, there are two reasons for this
+ 1. old entry may have different addresses.
+ 2. even if entry with correct addresses is already in the cache,
+ but if it is close to expire, then by the time next http
+ request is made, it can get expired and pruned because old
+ entry is not necessarily marked as added by CURLOPT_RESOLVE. */
+
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ }
/* free the allocated entry_id again */
free(entry_id);
- if(!dns) {
- /* if not in the cache already, put this host in the cache */
- 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
- * entry alive: */
- dns->inuse--;
- }
- }
- else {
- /* this is a duplicate, free it again */
- infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
- hostname, port, addresses);
- Curl_freeaddrinfo(head);
+ /* put this new host in the cache */
+ 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
+ * entry alive: */
+ dns->inuse--;
}
if(data->share)
@@ -1045,3 +1058,54 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
return CURLE_OK;
}
+
+CURLcode Curl_resolv_check(struct connectdata *conn,
+ struct Curl_dns_entry **dns)
+{
+ if(conn->data->set.doh)
+ return Curl_doh_is_resolved(conn, dns);
+ return Curl_resolver_is_resolved(conn, dns);
+}
+
+int Curl_resolv_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+#ifdef CURLRES_ASYNCH
+ if(conn->data->set.doh)
+ /* nothing to wait for during DOH resolve, those handles have their own
+ sockets */
+ return GETSOCK_BLANK;
+ return Curl_resolver_getsock(conn, socks, numsocks);
+#else
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return GETSOCK_BLANK;
+#endif
+}
+
+/* Call this function after Curl_connect() has returned async=TRUE and
+ then a successful name resolve has been received.
+
+ Note: this function disconnects and frees the conn data in case of
+ resolve failure */
+CURLcode Curl_once_resolved(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result;
+
+ if(conn->async.dns) {
+ conn->dns_entry = conn->async.dns;
+ conn->async.dns = NULL;
+ }
+
+ result = Curl_setup_conn(conn, protocol_done);
+
+ if(result)
+ /* We're not allowed to return failure with memory left allocated
+ in the connectdata struct, free those here */
+ Curl_disconnect(conn->data, conn, TRUE); /* close the connection */
+
+ return result;
+}
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 1de4bee8d..29fd1ef7c 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -145,12 +145,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
/* IPv4 threadsafe resolve function used for synch and asynch builds */
Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
-CURLcode Curl_async_resolved(struct connectdata *conn,
- bool *protocol_connect);
-
-#ifndef CURLRES_ASYNCH
-#define Curl_async_resolved(x,y) CURLE_OK
-#endif
+CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
/*
* Curl_addrinfo_callback() is used when we build with any asynch specialty.
@@ -258,4 +253,10 @@ void Curl_hostcache_destroy(struct Curl_easy *data);
*/
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
+CURLcode Curl_resolv_check(struct connectdata *conn,
+ struct Curl_dns_entry **dns);
+int Curl_resolv_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/Utilities/cmcurl/lib/hostip6.c b/Utilities/cmcurl/lib/hostip6.c
index 7c9988f41..3bf47b467 100644
--- a/Utilities/cmcurl/lib/hostip6.c
+++ b/Utilities/cmcurl/lib/hostip6.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,39 +59,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
-/* These are strictly for memory tracing and are using the same style as the
- * family otherwise present in memdebug.c. I put these ones here since they
- * require a bunch of structs I didn't want to include in memdebug.c
- */
-
-/*
- * For CURLRES_ARS, this should be written using ares_gethostbyaddr()
- * (ignoring the fact c-ares doesn't return 'serv').
- */
-
-int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
- GETNAMEINFO_TYPE_ARG2 salen,
- char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
- char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
- GETNAMEINFO_TYPE_ARG7 flags,
- int line, const char *source)
-{
- int res = (getnameinfo)(sa, salen,
- host, hostlen,
- serv, servlen,
- flags);
- if(0 == res)
- /* success */
- curl_memlog("GETNAME %s:%d getnameinfo()\n",
- source, line);
- else
- curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n",
- source, line, res);
- return res;
-}
-#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
-
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index ff1d6813a..46ac15a6e 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -158,18 +158,20 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct HTTP *http;
- DEBUGASSERT(conn->data->req.protop == NULL);
+ struct Curl_easy *data = conn->data;
+ DEBUGASSERT(data->req.protop == NULL);
http = calloc(1, sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
Curl_mime_initpart(&http->form, conn->data);
- conn->data->req.protop = http;
-
- Curl_http2_setup_conn(conn);
- Curl_http2_setup_req(conn->data);
+ data->req.protop = http;
+ if(!CONN_INUSE(conn))
+ /* if not already multi-using, setup connection details */
+ Curl_http2_setup_conn(conn);
+ Curl_http2_setup_req(data);
return CURLE_OK;
}
@@ -310,22 +312,49 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
return result;
}
+/*
+ * http_output_bearer() sets up an Authorization: header
+ * for HTTP Bearer authentication.
+ *
+ * Returns CURLcode.
+ */
+static CURLcode http_output_bearer(struct connectdata *conn)
+{
+ char **userp;
+ CURLcode result = CURLE_OK;
+
+ userp = &conn->allocptr.userpwd;
+ free(*userp);
+ *userp = aprintf("Authorization: Bearer %s\r\n",
+ conn->oauth_bearer);
+
+ if(!*userp) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ fail:
+ return result;
+}
+
/* pickoneauth() selects the most favourable authentication method from the
* ones available and the ones we want.
*
* return TRUE if one was picked
*/
-static bool pickoneauth(struct auth *pick)
+static bool pickoneauth(struct auth *pick, unsigned long mask)
{
bool picked;
/* only deal with authentication we want */
- unsigned long avail = pick->avail & pick->want;
+ unsigned long avail = pick->avail & pick->want & mask;
picked = TRUE;
/* The order of these checks is highly relevant, as this will be the order
of preference in case of the existence of multiple accepted types. */
if(avail & CURLAUTH_NEGOTIATE)
pick->picked = CURLAUTH_NEGOTIATE;
+ else if(avail & CURLAUTH_BEARER)
+ pick->picked = CURLAUTH_BEARER;
else if(avail & CURLAUTH_DIGEST)
pick->picked = CURLAUTH_DIGEST;
else if(avail & CURLAUTH_NTLM)
@@ -479,6 +508,10 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
bool pickhost = FALSE;
bool pickproxy = FALSE;
CURLcode result = CURLE_OK;
+ unsigned long authmask = ~0ul;
+
+ if(!conn->oauth_bearer)
+ authmask &= (unsigned long)~CURLAUTH_BEARER;
if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
/* this is a transient response code, ignore */
@@ -487,30 +520,23 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
if(data->state.authproblem)
return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
- if(conn->bits.user_passwd &&
+ if((conn->bits.user_passwd || conn->oauth_bearer) &&
((data->req.httpcode == 401) ||
(conn->bits.authneg && data->req.httpcode < 300))) {
- pickhost = pickoneauth(&data->state.authhost);
+ pickhost = pickoneauth(&data->state.authhost, authmask);
if(!pickhost)
data->state.authproblem = TRUE;
}
if(conn->bits.proxy_user_passwd &&
((data->req.httpcode == 407) ||
(conn->bits.authneg && data->req.httpcode < 300))) {
- pickproxy = pickoneauth(&data->state.authproxy);
+ pickproxy = pickoneauth(&data->state.authproxy,
+ authmask & ~CURLAUTH_BEARER);
if(!pickproxy)
data->state.authproblem = TRUE;
}
if(pickhost || pickproxy) {
- /* In case this is GSS auth, the newurl field is already allocated so
- we must make sure to free it before allocating a new one. As figured
- out in bug #2284386 */
- Curl_safefree(data->req.newurl);
- data->req.newurl = strdup(data->change.url); /* clone URL */
- if(!data->req.newurl)
- return CURLE_OUT_OF_MEMORY;
-
if((data->set.httpreq != HTTPREQ_GET) &&
(data->set.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) {
@@ -518,6 +544,13 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
if(result)
return result;
}
+ /* In case this is GSS auth, the newurl field is already allocated so
+ we must make sure to free it before allocating a new one. As figured
+ out in bug #2284386 */
+ Curl_safefree(data->req.newurl);
+ data->req.newurl = strdup(data->change.url); /* clone URL */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
}
else if((data->req.httpcode < 300) &&
(!data->state.authhost.done) &&
@@ -628,6 +661,20 @@ output_auth_headers(struct connectdata *conn,
functions work that way */
authstatus->done = TRUE;
}
+ if(authstatus->picked == CURLAUTH_BEARER) {
+ /* Bearer */
+ if((!proxy && conn->oauth_bearer &&
+ !Curl_checkheaders(conn, "Authorization:"))) {
+ auth = "Bearer";
+ result = http_output_bearer(conn);
+ if(result)
+ return result;
+ }
+
+ /* NOTE: this function should set 'done' TRUE, as the other auth
+ functions work that way */
+ authstatus->done = TRUE;
+ }
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
@@ -674,7 +721,7 @@ Curl_http_output_auth(struct connectdata *conn,
authproxy = &data->state.authproxy;
if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
- conn->bits.user_passwd)
+ conn->bits.user_passwd || conn->oauth_bearer)
/* continue please */;
else {
authhost->done = TRUE;
@@ -883,6 +930,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
data->state.authproblem = TRUE;
}
}
+ else
+ if(checkprefix("Bearer", auth)) {
+ *availp |= CURLAUTH_BEARER;
+ authp->avail |= CURLAUTH_BEARER;
+ if(authp->picked == CURLAUTH_BEARER) {
+ /* We asked for Bearer authentication but got a 40X back
+ anyway, which basically means our token isn't valid. */
+ authp->avail = CURLAUTH_NONE;
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
/* there may be multiple methods on one line, so keep reading */
while(*auth && *auth != ',') /* read up to the next comma */
@@ -1034,11 +1093,13 @@ Curl_send_buffer *Curl_add_buffer_init(void)
/*
* Curl_add_buffer_free() frees all associated resources.
*/
-void Curl_add_buffer_free(Curl_send_buffer *buff)
+void Curl_add_buffer_free(Curl_send_buffer **inp)
{
- if(buff) /* deal with NULL input */
- free(buff->buffer);
- free(buff);
+ Curl_send_buffer *in = *inp;
+ if(in) /* deal with NULL input */
+ free(in->buffer);
+ free(in);
+ *inp = NULL;
}
/*
@@ -1047,7 +1108,7 @@ void Curl_add_buffer_free(Curl_send_buffer *buff)
*
* Returns CURLcode
*/
-CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
struct connectdata *conn,
/* add the number of sent bytes to this
@@ -1063,10 +1124,12 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
CURLcode result;
char *ptr;
size_t size;
- struct HTTP *http = conn->data->req.protop;
+ struct Curl_easy *data = conn->data;
+ struct HTTP *http = data->req.protop;
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
+ Curl_send_buffer *in = *inp;
DEBUGASSERT(socketindex <= SECONDARYSOCKET);
@@ -1083,11 +1146,11 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
DEBUGASSERT(size > included_body_bytes);
- result = Curl_convert_to_network(conn->data, ptr, headersize);
+ result = Curl_convert_to_network(data, ptr, headersize);
/* Curl_convert_to_network calls failf if unsuccessful */
if(result) {
/* conversion failed, free memory and return to the caller */
- Curl_add_buffer_free(in);
+ Curl_add_buffer_free(inp);
return result;
}
@@ -1108,8 +1171,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
must copy the data to the uploadbuffer first, since that is the buffer
we will be using if this send is retried later.
*/
- memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
- ptr = conn->data->state.uploadbuffer;
+ result = Curl_get_upload_buffer(data);
+ if(result) {
+ /* malloc failed, free memory and return to the caller */
+ Curl_add_buffer_free(&in);
+ return result;
+ }
+ memcpy(data->state.ulbuf, ptr, sendsize);
+ ptr = data->state.ulbuf;
}
else
sendsize = size;
@@ -1126,14 +1195,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
size_t bodylen = amount - headlen;
- if(conn->data->set.verbose) {
+ if(data->set.verbose) {
/* this data _may_ contain binary stuff */
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
+ Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
if(bodylen) {
/* there was body data sent beyond the initial header part, pass that
on to the debug callback too */
- Curl_debug(conn->data, CURLINFO_DATA_OUT,
- ptr + headlen, bodylen, conn);
+ Curl_debug(data, CURLINFO_DATA_OUT,
+ ptr + headlen, bodylen);
}
}
@@ -1157,14 +1226,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
ptr = in->buffer + amount;
/* backup the currently set pointers */
- http->backup.fread_func = conn->data->state.fread_func;
- http->backup.fread_in = conn->data->state.in;
+ http->backup.fread_func = data->state.fread_func;
+ http->backup.fread_in = data->state.in;
http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize;
/* set the new pointers for the request-sending */
- conn->data->state.fread_func = (curl_read_callback)readmoredata;
- conn->data->state.in = (void *)conn;
+ data->state.fread_func = (curl_read_callback)readmoredata;
+ data->state.in = (void *)conn;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
@@ -1189,7 +1258,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
Curl_pipeline_leave_write(conn);
}
}
- Curl_add_buffer_free(in);
+ Curl_add_buffer_free(&in);
return result;
}
@@ -1198,32 +1267,35 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
/*
* add_bufferf() add the formatted input to the buffer.
*/
-CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
+CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
{
char *s;
va_list ap;
+ Curl_send_buffer *in = *inp;
va_start(ap, fmt);
s = vaprintf(fmt, ap); /* this allocs a new string to append */
va_end(ap);
if(s) {
- CURLcode result = Curl_add_buffer(in, s, strlen(s));
+ CURLcode result = Curl_add_buffer(inp, s, strlen(s));
free(s);
return result;
}
/* If we failed, we cleanup the whole buffer and return error */
free(in->buffer);
free(in);
+ *inp = NULL;
return CURLE_OUT_OF_MEMORY;
}
/*
- * add_buffer() appends a memory chunk to the existing buffer
+ * Curl_add_buffer() appends a memory chunk to the existing buffer
*/
-CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
+CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
+ size_t size)
{
char *new_rb;
- size_t new_size;
+ Curl_send_buffer *in = *inp;
if(~size < in->size_used) {
/* If resulting used size of send buffer would wrap size_t, cleanup
@@ -1231,15 +1303,16 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
size will fit into a single allocatable memory chunk */
Curl_safefree(in->buffer);
free(in);
+ *inp = NULL;
return CURLE_OUT_OF_MEMORY;
}
if(!in->buffer ||
((in->size_used + size) > (in->size_max - 1))) {
-
/* If current buffer size isn't enough to hold the result, use a
buffer size that doubles the required size. If this new size
would wrap size_t, then just use the largest possible one */
+ size_t new_size;
if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
(~(size * 2) < (in->size_used * 2)))
@@ -1257,6 +1330,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
if(!new_rb) {
/* If we failed, we cleanup the whole buffer and return error */
free(in);
+ *inp = NULL;
return CURLE_OUT_OF_MEMORY;
}
@@ -1406,7 +1480,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
}
snprintf(proxy_header,
- sizeof proxy_header,
+ sizeof(proxy_header),
"PROXY %s %s %s %li %li\r\n",
tcp_version,
conn->data->info.conn_local_ip,
@@ -1418,11 +1492,11 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
if(!req_buffer)
return CURLE_OUT_OF_MEMORY;
- result = Curl_add_bufferf(req_buffer, proxy_header);
+ result = Curl_add_bufferf(&req_buffer, proxy_header);
if(result)
return result;
- result = Curl_add_buffer_send(req_buffer,
+ result = Curl_add_buffer_send(&req_buffer,
conn,
&conn->data->info.request_size,
0,
@@ -1495,8 +1569,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
return CURLE_OK;
if(http->send_buffer) {
- Curl_add_buffer_free(http->send_buffer);
- http->send_buffer = NULL; /* clear the pointer */
+ Curl_add_buffer_free(&http->send_buffer);
}
Curl_http2_done(conn, premature);
@@ -1574,7 +1647,6 @@ static CURLcode expect100(struct Curl_easy *data,
Curl_send_buffer *req_buffer)
{
CURLcode result = CURLE_OK;
- const char *ptr;
data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */
if(use_http_1_1plus(data, conn) &&
@@ -1582,14 +1654,14 @@ 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");
+ const char *ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
}
else {
- result = Curl_add_bufferf(req_buffer,
- "Expect: 100-continue\r\n");
+ result = Curl_add_bufferf(&req_buffer,
+ "Expect: 100-continue\r\n");
if(!result)
data->state.expect100header = TRUE;
}
@@ -1720,7 +1792,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
- result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
+ result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data);
}
if(semicolonp)
*semicolonp = ';'; /* put back the semicolon */
@@ -1789,7 +1861,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
tm->tm_min,
tm->tm_sec);
- result = Curl_add_buffer(req_buffer, datestr, strlen(datestr));
+ result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
return result;
}
@@ -1804,7 +1876,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct HTTP *http;
- const char *ppath = data->state.path;
+ const char *path = data->state.up.path;
+ const char *query = data->state.up.query;
bool paste_ftp_userpwd = FALSE;
char ftp_typecode[sizeof("/;type=?")] = "";
const char *host = conn->host.name;
@@ -1819,7 +1892,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
const char *httpstring;
Curl_send_buffer *req_buffer;
curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
- int seekerr = CURL_SEEKFUNC_CANTSEEK;
/* Always consider the DO phase done after this function call, even if there
may be parts of the request that is not yet sent, since we can deal with
@@ -1863,6 +1935,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
http = data->req.protop;
+ DEBUGASSERT(http);
if(!data->state.this_is_a_follow) {
/* Free to avoid leaking memory on multiple requests*/
@@ -1922,7 +1995,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
/* setup the authentication headers */
- result = Curl_http_output_auth(conn, request, ppath, FALSE);
+ result = Curl_http_output_auth(conn, request, path, FALSE);
if(result)
return result;
@@ -2088,7 +2161,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else {
/* If the host begins with '[', we start searching for the port after
the bracket has been closed */
- int startsearch = 0;
if(*cookiehost == '[') {
char *closingbracket;
/* since the 'cookiehost' is an allocated memory area that will be
@@ -2099,6 +2171,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
*closingbracket = 0;
}
else {
+ int startsearch = 0;
char *colon = strchr(cookiehost + startsearch, ':');
if(colon)
*colon = 0; /* The host must not include an embedded port number */
@@ -2150,47 +2223,59 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* The path sent to the proxy is in fact the entire URL. But if the remote
host is a IDN-name, we must make sure that the request we produce only
uses the encoded host name! */
+
+ /* and no fragment part */
+ CURLUcode uc;
+ char *url;
+ CURLU *h = curl_url_dup(data->state.uh);
+ if(!h)
+ return CURLE_OUT_OF_MEMORY;
+
if(conn->host.dispname != conn->host.name) {
- char *url = data->change.url;
- ptr = strstr(url, conn->host.dispname);
- if(ptr) {
- /* This is where the display name starts in the URL, now replace this
- part with the encoded name. TODO: This method of replacing the host
- name is rather crude as I believe there's a slight risk that the
- user has entered a user name or password that contain the host name
- string. */
- size_t currlen = strlen(conn->host.dispname);
- size_t newlen = strlen(conn->host.name);
- size_t urllen = strlen(url);
-
- char *newurl;
-
- newurl = malloc(urllen + newlen - currlen + 1);
- if(newurl) {
- /* copy the part before the host name */
- memcpy(newurl, url, ptr - url);
- /* append the new host name instead of the old */
- memcpy(newurl + (ptr - url), conn->host.name, newlen);
- /* append the piece after the host name */
- memcpy(newurl + newlen + (ptr - url),
- ptr + currlen, /* copy the trailing zero byte too */
- urllen - (ptr-url) - currlen + 1);
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
- data->change.url = newurl;
- data->change.url_alloc = TRUE;
- }
- else
- return CURLE_OUT_OF_MEMORY;
+ uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(strcasecompare("http", data->state.up.scheme)) {
+ /* when getting HTTP, we don't want the userinfo the URL */
+ uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
}
+ uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ /* now extract the new version of the URL */
+ uc = curl_url_get(h, CURLUPART_URL, &url, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
}
- ppath = data->change.url;
- if(checkprefix("ftp://", ppath)) {
+
+ if(data->change.url_alloc)
+ free(data->change.url);
+
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
+
+ curl_url_cleanup(h);
+
+ if(strcasecompare("ftp", data->state.up.scheme)) {
if(data->set.proxy_transfer_mode) {
/* when doing ftp, append ;type=<a|i> if not present */
- char *type = strstr(ppath, ";type=");
+ char *type = strstr(path, ";type=");
if(type && type[6] && type[7] == 0) {
switch(Curl_raw_toupper(type[6])) {
case 'A':
@@ -2205,7 +2290,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
char *p = ftp_typecode;
/* avoid sending invalid URLs like ftp://example.com;type=i if the
* user specified ftp://example.com without the slash */
- if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
+ if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
*p++ = '/';
}
snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
@@ -2244,6 +2329,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Now, let's read off the proper amount of bytes from the
input. */
+ int seekerr = CURL_SEEKFUNC_CANTSEEK;
if(conn->seek_func) {
Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
@@ -2353,25 +2439,36 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* add the main request stuff */
/* GET/HEAD/POST/PUT */
- result = Curl_add_bufferf(req_buffer, "%s ", request);
+ result = Curl_add_bufferf(&req_buffer, "%s ", request);
if(result)
return result;
- if(data->set.str[STRING_TARGET])
- ppath = data->set.str[STRING_TARGET];
+ if(data->set.str[STRING_TARGET]) {
+ path = data->set.str[STRING_TARGET];
+ query = NULL;
+ }
/* url */
- if(paste_ftp_userpwd)
- result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ char *url = data->change.url;
+ result = Curl_add_buffer(&req_buffer, url, strlen(url));
+ }
+ else if(paste_ftp_userpwd)
+ result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s",
conn->user, conn->passwd,
- ppath + sizeof("ftp://") - 1);
- else
- result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
+ path + sizeof("ftp://") - 1);
+ else {
+ result = Curl_add_buffer(&req_buffer, path, strlen(path));
+ if(result)
+ return result;
+ if(query)
+ result = Curl_add_bufferf(&req_buffer, "?%s", query);
+ }
if(result)
return result;
result =
- Curl_add_bufferf(req_buffer,
+ Curl_add_bufferf(&req_buffer,
"%s" /* ftp typecode (;type=x) */
" HTTP/%s\r\n" /* HTTP version */
"%s" /* host */
@@ -2441,7 +2538,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
co = Curl_cookie_getlist(data->cookies,
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:host,
- data->state.path,
+ data->state.up.path,
(conn->handler->protocol&CURLPROTO_HTTPS)?
TRUE:FALSE);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
@@ -2452,11 +2549,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
while(co) {
if(co->value) {
if(0 == count) {
- result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ result = Curl_add_bufferf(&req_buffer, "Cookie: ");
if(result)
break;
}
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"%s%s=%s", count?"; ":"",
co->name, co->value);
if(result)
@@ -2469,15 +2566,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(addcookies && !result) {
if(!count)
- result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ result = Curl_add_bufferf(&req_buffer, "Cookie: ");
if(!result) {
- result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"",
+ result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"",
addcookies);
count++;
}
}
if(count && !result)
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
@@ -2511,7 +2608,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if((postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize);
if(result)
@@ -2524,7 +2621,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */
if(result)
return result;
@@ -2532,7 +2629,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_pgrsSetUploadSize(data, postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending PUT request");
@@ -2550,11 +2647,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* This is form posting using mime data. */
if(conn->bits.authneg) {
/* nothing to post! */
- result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
+ result = Curl_add_bufferf(&req_buffer, "Content-Length: 0\r\n\r\n");
if(result)
return result;
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
@@ -2574,7 +2671,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(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,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize);
if(result)
@@ -2586,7 +2683,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
struct curl_slist *hdr;
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
- result = Curl_add_bufferf(req_buffer, "%s\r\n", hdr->data);
+ result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data);
if(result)
return result;
}
@@ -2610,7 +2707,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->state.expect100header = FALSE;
/* make the request end in a true CRLF */
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
@@ -2623,7 +2720,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
@@ -2653,7 +2750,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(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,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize);
if(result)
@@ -2661,7 +2758,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Type: application/"
"x-www-form-urlencoded\r\n");
if(result)
@@ -2699,31 +2796,31 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
is no magic limit but only set to prevent really huge POSTs to
get the data duplicated with malloc() and family. */
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result)
return result;
if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
- result = Curl_add_buffer(req_buffer, data->set.postfields,
+ result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize);
included_body = postsize;
}
else {
if(postsize) {
/* Append the POST data chunky-style */
- result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
+ result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize);
if(!result) {
- result = Curl_add_buffer(req_buffer, data->set.postfields,
+ result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize);
if(!result)
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
included_body = postsize + 2;
}
}
if(!result)
- result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
+ result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
/* 0 CR LF CR LF */
included_body += 5;
}
@@ -2745,20 +2842,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result)
return result;
}
}
else {
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result)
return result;
if(data->req.upload_chunky && conn->bits.authneg) {
/* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */
- result = Curl_add_buffer(req_buffer,
+ result = Curl_add_buffer(&req_buffer,
"\x30\x0d\x0a\x0d\x0a", 5);
/* 0 CR LF CR LF */
if(result)
@@ -2779,7 +2876,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
/* issue the request */
- result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
+ result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size,
(size_t)included_body, FIRSTSOCKET);
if(result)
@@ -2791,12 +2888,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
default:
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
/* issue the request */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
@@ -2828,6 +2925,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->req.exp100 = EXP100_SEND_DATA; /* already sent */
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
}
+ else
+ data->req.writebytecount = http->writebytecount;
}
if((conn->httpversion == 20) && data->req.upload_chunky)
@@ -2838,17 +2937,32 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
+typedef enum {
+ STATUS_UNKNOWN, /* not enough data to tell yet */
+ STATUS_DONE, /* a status line was read */
+ STATUS_BAD /* not a status line */
+} statusline;
+
+
+/* Check a string for a prefix. Check no more than 'len' bytes */
+static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
+{
+ size_t ch = CURLMIN(strlen(prefix), len);
+ return curl_strnequal(prefix, buffer, ch);
+}
+
/*
* checkhttpprefix()
*
* Returns TRUE if member of the list matches prefix of string
*/
-static bool
+static statusline
checkhttpprefix(struct Curl_easy *data,
- const char *s)
+ const char *s, size_t len)
{
struct curl_slist *head = data->set.http200aliases;
- bool rc = FALSE;
+ statusline rc = STATUS_BAD;
+ statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding using a scratch area */
char *scratch = strdup(s);
@@ -2865,15 +2979,15 @@ checkhttpprefix(struct Curl_easy *data,
#endif /* CURL_DOES_CONVERSIONS */
while(head) {
- if(checkprefix(head->data, s)) {
- rc = TRUE;
+ if(checkprefixmax(head->data, s, len)) {
+ rc = onmatch;
break;
}
head = head->next;
}
- if(!rc && (checkprefix("HTTP/", s)))
- rc = TRUE;
+ if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
+ rc = onmatch;
#ifdef CURL_DOES_CONVERSIONS
free(scratch);
@@ -2882,11 +2996,12 @@ checkhttpprefix(struct Curl_easy *data,
}
#ifndef CURL_DISABLE_RTSP
-static bool
+static statusline
checkrtspprefix(struct Curl_easy *data,
- const char *s)
+ const char *s, size_t len)
{
- bool result = FALSE;
+ statusline result = STATUS_BAD;
+ statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding using a scratch area */
@@ -2899,30 +3014,31 @@ checkrtspprefix(struct Curl_easy *data,
/* Curl_convert_from_network calls failf if unsuccessful */
result = FALSE; /* can't return CURLE_foobar so return FALSE */
}
- else
- result = checkprefix("RTSP/", scratch)? TRUE: FALSE;
+ else if(checkprefixmax("RTSP/", scratch, len))
+ result = onmatch;
free(scratch);
#else
(void)data; /* unused */
- result = checkprefix("RTSP/", s)? TRUE: FALSE;
+ if(checkprefixmax("RTSP/", s, len))
+ result = onmatch;
#endif /* CURL_DOES_CONVERSIONS */
return result;
}
#endif /* CURL_DISABLE_RTSP */
-static bool
+static statusline
checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
- const char *s)
+ const char *s, size_t len)
{
#ifndef CURL_DISABLE_RTSP
if(conn->handler->protocol & CURLPROTO_RTSP)
- return checkrtspprefix(data, s);
+ return checkrtspprefix(data, s, len);
#else
(void)conn;
#endif /* CURL_DISABLE_RTSP */
- return checkhttpprefix(data, s);
+ return checkhttpprefix(data, s, len);
}
/*
@@ -2939,7 +3055,7 @@ static CURLcode header_append(struct Curl_easy *data,
/* 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,
+ failf(data, "Rejected %zu bytes header (max is %d)!", newsize,
CURL_MAX_HTTP_HEADER);
return CURLE_OUT_OF_MEMORY;
}
@@ -3036,12 +3152,15 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(result)
return result;
- if(!k->headerline && (k->hbuflen>5)) {
- /* make a first check that this looks like a protocol header */
- if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
+ if(!k->headerline) {
+ /* check if this looks like a protocol header */
+ statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
+ k->hbuflen);
+ if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
k->badheader = HEADER_ALLBAD;
+ streamclose(conn, "bad HTTP: No end-of-message indicator");
break;
}
}
@@ -3070,8 +3189,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(!k->headerline) {
/* the first read header */
- if((k->hbuflen>5) &&
- !checkprotoprefix(data, conn, data->state.headerbuff)) {
+ statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
+ k->hbuflen);
+ if(st == STATUS_BAD) {
+ streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
if(*nread)
@@ -3354,7 +3475,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- k->str_start, headerlen, conn);
+ k->str_start, headerlen);
break; /* exit header line loop */
}
@@ -3440,7 +3561,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
compare header line against list of aliases
*/
if(!nc) {
- if(checkhttpprefix(data, k->p)) {
+ if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) {
nc = 1;
k->httpcode = 200;
conn->httpversion = 10;
@@ -3487,21 +3608,18 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* depending on how authentication is working. Other codes
* are definitely errors, so give up here.
*/
- if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
+ if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET &&
+ k->httpcode == 416) {
+ /* "Requested Range Not Satisfiable", just proceed and
+ pretend this is no error */
+ k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
+ }
+ else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
((k->httpcode != 401) || !conn->bits.user_passwd) &&
((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
-
- if(data->state.resume_from &&
- (data->set.httpreq == HTTPREQ_GET) &&
- (k->httpcode == 416)) {
- /* "Requested Range Not Satisfiable", just proceed and
- pretend this is no error */
- }
- else {
- /* serious error, go home! */
- print_http_error(data);
- return CURLE_HTTP_RETURNED_ERROR;
- }
+ /* serious error, go home! */
+ print_http_error(data);
+ return CURLE_HTTP_RETURNED_ERROR;
}
if(conn->httpversion == 10) {
@@ -3741,7 +3859,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
here, or else use real peer host name. */
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:conn->host.name,
- data->state.path);
+ data->state.up.path);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
#endif
@@ -3812,8 +3930,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
writetype |= CLIENTWRITE_BODY;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- k->p, (size_t)k->hbuflen, conn);
+ Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen);
result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
if(result)
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index 1d373e8f4..21fa701ab 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -58,10 +58,12 @@ struct Curl_send_buffer {
typedef struct Curl_send_buffer Curl_send_buffer;
Curl_send_buffer *Curl_add_buffer_init(void);
-void Curl_add_buffer_free(Curl_send_buffer *buff);
-CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...);
-CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size);
-CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+void Curl_add_buffer_free(Curl_send_buffer **inp);
+CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
+ WARN_UNUSED_RESULT;
+CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
+ size_t size) WARN_UNUSED_RESULT;
+CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
struct connectdata *conn,
long *bytes_written,
size_t included_body_bytes,
@@ -154,9 +156,11 @@ struct HTTP {
HTTPSEND_LAST /* never use this */
} sending;
- void *send_buffer; /* used if the request couldn't be sent in one chunk,
- points to an allocated send_buffer struct */
-
+#ifndef CURL_DISABLE_HTTP
+ Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in
+ one chunk, points to an allocated
+ send_buffer struct */
+#endif
#ifdef USE_NGHTTP2
/*********** for HTTP/2 we store stream-local data here *************/
int32_t stream_id; /* stream we are interested in */
@@ -253,4 +257,3 @@ Curl_http_output_auth(struct connectdata *conn,
up the proxy tunnel */
#endif /* HEADER_CURL_HTTP_H */
-
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index da001dfd0..0c5f6db0b 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -42,7 +42,6 @@
#include "memdebug.h"
#define H2_BUFSIZE 32768
-#define MIN(x,y) ((x)<(y)?(x):(y))
#if (NGHTTP2_VERSION_NUM < 0x010000)
#error too old nghttp2 version, upgrade!
@@ -142,10 +141,8 @@ static int http2_getsock(struct connectdata *conn,
static void http2_stream_free(struct HTTP *http)
{
if(http) {
- Curl_add_buffer_free(http->header_recvbuf);
- http->header_recvbuf = NULL; /* clear the pointer */
- Curl_add_buffer_free(http->trailer_recvbuf);
- http->trailer_recvbuf = NULL; /* clear the pointer */
+ Curl_add_buffer_free(&http->header_recvbuf);
+ Curl_add_buffer_free(&http->trailer_recvbuf);
for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]);
}
@@ -154,6 +151,11 @@ static void http2_stream_free(struct HTTP *http)
}
}
+/*
+ * Disconnects *a* connection used for HTTP/2. It might be an old one from the
+ * connection cache and not the "main" one. Don't touch the easy handle!
+ */
+
static CURLcode http2_disconnect(struct connectdata *conn,
bool dead_connection)
{
@@ -164,8 +166,6 @@ static CURLcode http2_disconnect(struct connectdata *conn,
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
- http2_stream_free(conn->data->req.protop);
- conn->data->state.drain = 0;
H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
@@ -201,7 +201,7 @@ static bool http2_connisdead(struct connectdata *conn)
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,
+ not in use by any other transfer, there shouldn't be any data here,
only "protocol frames" */
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
@@ -231,12 +231,43 @@ static unsigned int http2_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
+ struct http_conn *c = &check->proto.httpc;
+ int rc;
+ bool send_frames = false;
if(checks_to_perform & CONNCHECK_ISDEAD) {
if(http2_connisdead(check))
ret_val |= CONNRESULT_DEAD;
}
+ if(checks_to_perform & CONNCHECK_KEEPALIVE) {
+ struct curltime now = Curl_now();
+ time_t elapsed = Curl_timediff(now, check->keepalive);
+
+ if(elapsed > check->upkeep_interval_ms) {
+ /* Perform an HTTP/2 PING */
+ rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
+ if(!rc) {
+ /* Successfully added a PING frame to the session. Need to flag this
+ so the frame is sent. */
+ send_frames = true;
+ }
+ else {
+ failf(check->data, "nghttp2_submit_ping() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ }
+
+ check->keepalive = now;
+ }
+ }
+
+ if(send_frames) {
+ rc = nghttp2_session_send(c->h2);
+ if(rc)
+ failf(check->data, "nghttp2_session_send() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ }
+
return ret_val;
}
@@ -345,7 +376,7 @@ const char *Curl_http2_strerror(uint32_t err)
"INADEQUATE_SECURITY", /* 0xC */
"HTTP_1_1_REQUIRED" /* 0xD */
};
- return (err < sizeof str / sizeof str[0]) ? str[err] : "unknown";
+ return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown";
#else
return nghttp2_http2_strerror(err);
#endif
@@ -368,6 +399,10 @@ static ssize_t send_callback(nghttp2_session *h2,
(void)h2;
(void)flags;
+ if(!c->send_underlying)
+ /* called before setup properly! */
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET,
data, length, &result);
@@ -441,6 +476,28 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
return NULL;
}
+/*
+ * This specific transfer on this connection has been "drained".
+ */
+static void drained_transfer(struct Curl_easy *data,
+ struct http_conn *httpc)
+{
+ DEBUGASSERT(httpc->drain_total >= data->state.drain);
+ httpc->drain_total -= data->state.drain;
+ data->state.drain = 0;
+}
+
+/*
+ * Mark this transfer to get "drained".
+ */
+static void drain_this(struct Curl_easy *data,
+ struct http_conn *httpc)
+{
+ data->state.drain++;
+ httpc->drain_total++;
+ DEBUGASSERT(httpc->drain_total >= data->state.drain);
+}
+
static struct Curl_easy *duphandle(struct Curl_easy *data)
{
struct Curl_easy *second = curl_easy_duphandle(data);
@@ -520,6 +577,7 @@ static int push_promise(struct Curl_easy *data,
if(rv) {
/* denied, kill off the new handle again */
http2_stream_free(newhandle->req.protop);
+ newhandle->req.protop = NULL;
(void)Curl_close(newhandle);
goto fail;
}
@@ -535,14 +593,22 @@ static int push_promise(struct Curl_easy *data,
if(rc) {
infof(data, "failed to add handle to multi\n");
http2_stream_free(newhandle->req.protop);
+ newhandle->req.protop = NULL;
Curl_close(newhandle);
rv = 1;
goto fail;
}
httpc = &conn->proto.httpc;
- nghttp2_session_set_stream_user_data(httpc->h2,
- frame->promised_stream_id, newhandle);
+ rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ frame->promised_stream_id,
+ newhandle);
+ if(rv) {
+ infof(data, "failed to set user_data for stream %d\n",
+ frame->promised_stream_id);
+ DEBUGASSERT(0);
+ goto fail;
+ }
}
else {
H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
@@ -562,6 +628,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
int rv;
size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id;
+ CURLcode result;
if(!stream_id) {
/* stream ID zero is for connection-oriented stuff */
@@ -581,7 +648,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
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 == %d)!\n",
+ "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
httpc->settings.max_concurrent_streams);
Curl_multi_connchanged(conn->data->multi);
}
@@ -637,10 +704,12 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = -1;
}
- Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
+ result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
- ncopy = MIN(stream->len, left);
+ ncopy = CURLMIN(stream->len, left);
memcpy(&stream->mem[stream->memlen],
stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
@@ -653,8 +722,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream->len -= ncopy;
stream->memlen += ncopy;
- data_s->state.drain++;
- httpc->drain_total++;
+ drain_this(data_s, httpc);
{
/* get the pointer from userp again since it was re-assigned above */
struct connectdata *conn_s = (struct connectdata *)userp;
@@ -683,25 +751,6 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
return 0;
}
-static int on_invalid_frame_recv(nghttp2_session *session,
- const nghttp2_frame *frame,
- int lib_error_code, void *userp)
-{
- struct Curl_easy *data_s = NULL;
- (void)userp;
-#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) {
- H2BUGF(infof(data_s,
- "on_invalid_frame_recv() was called, error=%d:%s\n",
- lib_error_code, nghttp2_strerror(lib_error_code)));
- }
- return 0;
-}
-
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const uint8_t *data, size_t len, void *userp)
@@ -727,14 +776,13 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- nread = MIN(stream->len, len);
+ nread = CURLMIN(stream->len, len);
memcpy(&stream->mem[stream->memlen], data, nread);
stream->len -= nread;
stream->memlen += nread;
- data_s->state.drain++;
- conn->proto.httpc.drain_total++;
+ drain_this(data_s, &conn->proto.httpc);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
@@ -768,58 +816,13 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
return 0;
}
-static int before_frame_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- void *userp)
-{
- struct Curl_easy *data_s;
- (void)userp;
-
- data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
- if(data_s) {
- H2BUGF(infof(data_s, "before_frame_send() was called\n"));
- }
-
- return 0;
-}
-static int on_frame_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- void *userp)
-{
- struct Curl_easy *data_s;
- (void)userp;
-
- data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
- if(data_s) {
- H2BUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
- frame->hd.length));
- }
- return 0;
-}
-static int on_frame_not_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- int lib_error_code, void *userp)
-{
- struct Curl_easy *data_s;
- (void)userp;
-#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) {
- H2BUGF(infof(data_s,
- "on_frame_not_send() was called, lib_error_code = %d\n",
- lib_error_code));
- }
- return 0;
-}
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *userp)
{
struct Curl_easy *data_s;
struct HTTP *stream;
struct connectdata *conn = (struct connectdata *)userp;
+ int rv;
(void)session;
(void)stream_id;
@@ -840,14 +843,19 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
return NGHTTP2_ERR_CALLBACK_FAILURE;
stream->closed = TRUE;
- data_s->state.drain++;
httpc = &conn->proto.httpc;
- httpc->drain_total++;
+ drain_this(data_s, httpc);
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);
+ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
+ if(rv) {
+ infof(data_s, "http/2: failed to clear user_data for stream %d!\n",
+ stream_id);
+ DEBUGASSERT(0);
+ }
H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+ stream->stream_id = 0; /* cleared */
}
return 0;
}
@@ -922,6 +930,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id;
struct connectdata *conn = (struct connectdata *)userp;
+ CURLcode result;
(void)flags;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
@@ -948,6 +957,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->push_headers_alloc = 10;
stream->push_headers = malloc(stream->push_headers_alloc *
sizeof(char *));
+ if(!stream->push_headers)
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
stream->push_headers_used = 0;
}
else if(stream->push_headers_used ==
@@ -976,11 +987,21 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
- Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n));
- Curl_add_buffer(stream->trailer_recvbuf, name, namelen);
- Curl_add_buffer(stream->trailer_recvbuf, ": ", 2);
- Curl_add_buffer(stream->trailer_recvbuf, value, valuelen);
- Curl_add_buffer(stream->trailer_recvbuf, "\r\n\0", 3);
+ result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
return 0;
}
@@ -993,10 +1014,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = decode_status_code(value, valuelen);
DEBUGASSERT(stream->status_code != -1);
- Curl_add_buffer(stream->header_recvbuf, "HTTP/2 ", 7);
- Curl_add_buffer(stream->header_recvbuf, value, valuelen);
+ result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* the space character after the status code is mandatory */
- Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
+ result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
@@ -1009,10 +1036,18 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
/* convert to a HTTP1-style header */
- Curl_add_buffer(stream->header_recvbuf, name, namelen);
- Curl_add_buffer(stream->header_recvbuf, ": ", 2);
- Curl_add_buffer(stream->header_recvbuf, value, valuelen);
- Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
+ result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
@@ -1052,7 +1087,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
else
return NGHTTP2_ERR_INVALID_ARGUMENT;
- nread = MIN(stream->upload_len, length);
+ nread = CURLMIN(stream->upload_len, length);
if(nread > 0) {
memcpy(buf, stream->upload_mem, nread);
stream->upload_mem += nread;
@@ -1073,7 +1108,8 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
return nread;
}
-#ifdef NGHTTP2_HAS_ERROR_CALLBACK
+#if defined(NGHTTP2_HAS_ERROR_CALLBACK) && \
+ !defined(CURL_DISABLE_VERBOSE_STRINGS)
static int error_callback(nghttp2_session *session,
const char *msg,
size_t len,
@@ -1109,11 +1145,11 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
struct HTTP *http = data->req.protop;
struct http_conn *httpc = &conn->proto.httpc;
+ /* there might be allocated resources done before this got the 'h2' pointer
+ setup */
if(http->header_recvbuf) {
- Curl_add_buffer_free(http->header_recvbuf);
- http->header_recvbuf = NULL; /* clear the pointer */
- Curl_add_buffer_free(http->trailer_recvbuf);
- http->trailer_recvbuf = NULL; /* clear the pointer */
+ Curl_add_buffer_free(&http->header_recvbuf);
+ Curl_add_buffer_free(&http->trailer_recvbuf);
if(http->push_headers) {
/* if they weren't used and then freed before */
for(; http->push_headers_used > 0; --http->push_headers_used) {
@@ -1124,17 +1160,32 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
}
}
+ if(!httpc->h2) /* not HTTP/2 ? */
+ return;
+
+ if(data->state.drain)
+ drained_transfer(data, httpc);
+
if(premature) {
/* RST_STREAM */
- nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id,
- NGHTTP2_STREAM_CLOSED);
+ if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
+ http->stream_id, NGHTTP2_STREAM_CLOSED))
+ (void)nghttp2_session_send(httpc->h2);
+
if(http->stream_id == httpc->pause_stream_id) {
infof(data, "stopped the pause stream!\n");
httpc->pause_stream_id = 0;
}
}
- if(http->stream_id) {
- nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
+ /* -1 means unassigned and 0 means cleared */
+ if(http->stream_id > 0) {
+ int rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ http->stream_id, 0);
+ if(rv) {
+ infof(data, "http/2: failed to clear user_data for stream %d!\n",
+ http->stream_id);
+ DEBUGASSERT(0);
+ }
http->stream_id = 0;
}
}
@@ -1164,21 +1215,9 @@ CURLcode Curl_http2_init(struct connectdata *conn)
/* nghttp2_on_frame_recv_callback */
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv);
- /* nghttp2_on_invalid_frame_recv_callback */
- nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
- (callbacks, on_invalid_frame_recv);
/* nghttp2_on_data_chunk_recv_callback */
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv);
- /* nghttp2_before_frame_send_callback */
- nghttp2_session_callbacks_set_before_frame_send_callback
- (callbacks, before_frame_send);
- /* nghttp2_on_frame_send_callback */
- nghttp2_session_callbacks_set_on_frame_send_callback
- (callbacks, on_frame_send);
- /* nghttp2_on_frame_not_send_callback */
- nghttp2_session_callbacks_set_on_frame_not_send_callback
- (callbacks, on_frame_not_send);
/* nghttp2_on_stream_close_callback */
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close);
@@ -1188,7 +1227,9 @@ CURLcode Curl_http2_init(struct connectdata *conn)
/* nghttp2_on_header_callback */
nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
+#endif
/* The nghttp2 session is not yet setup, do it */
rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
@@ -1225,7 +1266,7 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
httpc->local_settings_num);
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
- Curl_add_buffer_free(req);
+ Curl_add_buffer_free(&req);
return CURLE_FAILED_INIT;
}
conn->proto.httpc.binlen = binlen;
@@ -1233,11 +1274,11 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen);
if(result) {
- Curl_add_buffer_free(req);
+ Curl_add_buffer_free(&req);
return result;
}
- result = Curl_add_bufferf(req,
+ result = Curl_add_bufferf(&req,
"Connection: Upgrade, HTTP2-Settings\r\n"
"Upgrade: %s\r\n"
"HTTP2-Settings: %s\r\n",
@@ -1280,7 +1321,7 @@ static int h2_process_pending_input(struct connectdata *conn,
if(rv < 0) {
failf(data,
"h2_process_pending_input: nghttp2_session_mem_recv() returned "
- "%d:%s\n", rv, nghttp2_strerror((int)rv));
+ "%zd:%s\n", rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
return -1;
}
@@ -1352,7 +1393,6 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
return result;
}
-
static ssize_t http2_handle_stream_close(struct connectdata *conn,
struct Curl_easy *data,
struct HTTP *stream, CURLcode *err)
@@ -1365,9 +1405,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
httpc->pause_stream_id = 0;
}
- DEBUGASSERT(httpc->drain_total >= data->state.drain);
- httpc->drain_total -= data->state.drain;
- data->state.drain = 0;
+ drained_transfer(data, httpc);
if(httpc->pause_stream_id == 0) {
if(h2_process_pending_input(conn, httpc, err) != 0) {
@@ -1388,7 +1426,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
return -1;
}
else if(httpc->error_code != NGHTTP2_NO_ERROR) {
- failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
+ failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
stream->stream_id, Curl_http2_strerror(httpc->error_code),
httpc->error_code);
*err = CURLE_HTTP2_STREAM;
@@ -1396,7 +1434,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
}
if(!stream->bodystarted) {
- failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
+ failf(data, "HTTP/2 stream %d was closed cleanly, but before getting "
" all response header fields, treated as error",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
@@ -1510,7 +1548,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* If there is body data pending for this stream to return, do that */
size_t left =
stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
- size_t ncopy = MIN(len, left);
+ size_t ncopy = CURLMIN(len, left);
memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
ncopy);
stream->nread_header_recvbuf += ncopy;
@@ -1546,13 +1584,13 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
}
else if(stream->pausedata) {
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
- nread = MIN(len, stream->pauselen);
+ nread = CURLMIN(len, stream->pauselen);
memcpy(mem, stream->pausedata, nread);
stream->pausedata += nread;
stream->pauselen -= nread;
- infof(data, "%zu data bytes written\n", nread);
+ infof(data, "%zd data bytes written\n", nread);
if(stream->pauselen == 0) {
H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
@@ -1635,7 +1673,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
if(nghttp2_is_fatal((int)rv)) {
- failf(data, "nghttp2_session_mem_recv() returned %d:%s\n",
+ failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
return -1;
@@ -1678,9 +1716,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
stream->stream_id));
}
else if(!stream->closed) {
- DEBUGASSERT(httpc->drain_total >= data->state.drain);
- httpc->drain_total -= data->state.drain;
- data->state.drain = 0; /* this stream is hereby drained */
+ drained_transfer(data, httpc);
}
return retlen;
@@ -2040,7 +2076,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
}
infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
- stream_id, conn->data);
+ stream_id, (void *)conn->data);
stream->stream_id = stream_id;
/* this does not call h2_session_send() since there can not have been any
@@ -2086,8 +2122,11 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
stream->stream_id = -1;
- if(!stream->header_recvbuf)
+ if(!stream->header_recvbuf) {
stream->header_recvbuf = Curl_add_buffer_init();
+ if(!stream->header_recvbuf)
+ return CURLE_OUT_OF_MEMORY;
+ }
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2))
@@ -2099,8 +2138,10 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
conn->handler = &Curl_handler_http2;
result = Curl_http2_init(conn);
- if(result)
+ if(result) {
+ Curl_add_buffer_free(&stream->header_recvbuf);
return result;
+ }
infof(conn->data, "Using HTTP2, server supports multi-use\n");
stream->upload_left = 0;
@@ -2154,9 +2195,14 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
return CURLE_HTTP2;
}
- nghttp2_session_set_stream_user_data(httpc->h2,
- stream->stream_id,
- conn->data);
+ rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ stream->stream_id,
+ data);
+ if(rv) {
+ infof(data, "http/2: failed to set user_data for stream %d!\n",
+ stream->stream_id);
+ DEBUGASSERT(0);
+ }
}
else {
populate_settings(conn, httpc);
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index f597c805e..4492ec211 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.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
@@ -65,7 +65,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup_conn(x)
+#define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
@@ -77,4 +77,3 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
#endif
#endif /* HEADER_CURL_HTTP2_H */
-
diff --git a/Utilities/cmcurl/lib/http_chunks.h b/Utilities/cmcurl/lib/http_chunks.h
index 3a8b4ddf3..b969c5590 100644
--- a/Utilities/cmcurl/lib/http_chunks.h
+++ b/Utilities/cmcurl/lib/http_chunks.h
@@ -88,4 +88,3 @@ struct Curl_chunker {
};
#endif /* HEADER_CURL_HTTP_CHUNKS_H */
-
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index fd5540b5d..a9b33f98e 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -228,7 +228,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
/* connection is already authenticated,
* don't send a header in future requests */
ntlm->state = NTLMSTATE_LAST;
- /* fall-through */
+ /* FALLTHROUGH */
case NTLMSTATE_LAST:
Curl_safefree(*allocuserpwd);
authp->done = TRUE;
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index e10a48829..2e0d92edd 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -188,12 +188,10 @@ static CURLcode CONNECT(struct connectdata *conn,
struct SingleRequest *k = &data->req;
CURLcode result;
curl_socket_t tunnelsocket = conn->sock[sockindex];
- timediff_t check;
struct http_connect_state *s = conn->connect_state;
#define SELECT_OK 0
#define SELECT_ERROR 1
-#define SELECT_TIMEOUT 2
if(Curl_connect_complete(conn))
return CURLE_OK; /* CONNECT is already completed */
@@ -201,12 +199,13 @@ static CURLcode CONNECT(struct connectdata *conn,
conn->bits.proxy_connect_closed = FALSE;
do {
+ timediff_t check;
if(TUNNEL_INIT == s->tunnel_state) {
/* BEGIN CONNECT PHASE */
char *host_port;
Curl_send_buffer *req_buffer;
- infof(data, "Establish HTTP proxy tunnel to %s:%hu\n",
+ infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
hostname, remote_port);
/* This only happens if we've looped here due to authentication
@@ -223,7 +222,7 @@ static CURLcode CONNECT(struct connectdata *conn,
host_port = aprintf("%s:%d", hostname, remote_port);
if(!host_port) {
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY;
}
@@ -248,7 +247,7 @@ static CURLcode CONNECT(struct connectdata *conn,
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY;
}
@@ -256,7 +255,7 @@ static CURLcode CONNECT(struct connectdata *conn,
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY;
}
}
@@ -268,7 +267,7 @@ static CURLcode CONNECT(struct connectdata *conn,
useragent = conn->allocptr.uagent;
result =
- Curl_add_bufferf(req_buffer,
+ Curl_add_bufferf(&req_buffer,
"CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */
"%s" /* Proxy-Authorization */
@@ -291,13 +290,13 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!result)
/* CRLF terminate the request */
- result = Curl_add_bufferf(req_buffer, "\r\n");
+ result = Curl_add_bufferf(&req_buffer, "\r\n");
if(!result) {
/* Send the connect request to the proxy */
/* BLOCKING */
result =
- Curl_add_buffer_send(req_buffer, conn,
+ Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, sockindex);
}
req_buffer = NULL;
@@ -305,7 +304,7 @@ static CURLcode CONNECT(struct connectdata *conn,
failf(data, "Failed sending CONNECT to proxy");
}
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
if(result)
return result;
@@ -419,7 +418,7 @@ static CURLcode CONNECT(struct connectdata *conn,
/* output debug if that is requested */
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- s->line_start, (size_t)s->perline, conn);
+ s->line_start, (size_t)s->perline);
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index cf278a22b..3ef89097f 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -159,7 +159,8 @@ const struct Curl_handler Curl_handler_imaps = {
ZERO_NULL, /* connection_check */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
- PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
+ PROTOPT_URLOPTIONS
};
#endif
@@ -421,7 +422,6 @@ static CURLcode imap_perform_capability(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
-
imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
imapc->tls_supported = FALSE; /* Clear the TLS capability */
@@ -609,7 +609,6 @@ static CURLcode imap_perform_list(struct connectdata *conn)
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
- char *mailbox;
if(imap->custom)
/* Send the custom request */
@@ -617,7 +616,8 @@ static CURLcode imap_perform_list(struct connectdata *conn)
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
- mailbox = imap->mailbox ? imap_atom(imap->mailbox, true) : strdup("");
+ char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true)
+ : strdup("");
if(!mailbox)
return CURLE_OUT_OF_MEMORY;
@@ -683,24 +683,37 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->req.protop;
-
/* Check we have a UID */
- if(!imap->uid) {
- failf(conn->data, "Cannot FETCH without a UID.");
- return CURLE_URL_MALFORMAT;
+ if(imap->uid) {
+
+ /* Send the FETCH command */
+ if(imap->partial)
+ result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>",
+ imap->uid,
+ imap->section ? imap->section : "",
+ imap->partial);
+ else
+ result = imap_sendf(conn, "UID FETCH %s BODY[%s]",
+ imap->uid,
+ imap->section ? imap->section : "");
+ }
+ else if(imap->mindex) {
+
+ /* Send the FETCH command */
+ if(imap->partial)
+ result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
+ imap->mindex,
+ imap->section ? imap->section : "",
+ imap->partial);
+ else
+ result = imap_sendf(conn, "FETCH %s BODY[%s]",
+ imap->mindex,
+ imap->section ? imap->section : "");
+ }
+ else {
+ failf(conn->data, "Cannot FETCH without a UID.");
+ return CURLE_URL_MALFORMAT;
}
-
- /* Send the FETCH command */
- if(imap->partial)
- result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
- imap->uid,
- imap->section ? imap->section : "",
- imap->partial);
- else
- result = imap_sendf(conn, "FETCH %s BODY[%s]",
- imap->uid,
- imap->section ? imap->section : "");
-
if(!result)
state(conn, IMAP_FETCH);
@@ -854,7 +867,6 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
- size_t wordlen;
(void)instate; /* no use for this yet */
@@ -864,6 +876,7 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
/* Loop through the data line */
for(;;) {
+ size_t wordlen;
while(*line &&
(*line == ' ' || *line == '\t' ||
*line == '\r' || *line == '\n')) {
@@ -1046,12 +1059,12 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
- char tmp[20];
(void)instate; /* no use for this yet */
if(imapcode == '*') {
/* See if this is an UIDVALIDITY response */
+ char tmp[20];
if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
Curl_safefree(imapc->mailbox_uidvalidity);
imapc->mailbox_uidvalidity = strdup(tmp);
@@ -1119,7 +1132,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
}
if(parsed) {
- infof(data, "Found %" CURL_FORMAT_CURL_OFF_TU " bytes to download\n",
+ infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n",
size);
Curl_pgrsSetDownloadSize(data, size);
@@ -1144,10 +1157,8 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
data->req.bytecount += chunk;
- infof(data, "Written %" CURL_FORMAT_CURL_OFF_TU
- " bytes, %" CURL_FORMAT_CURL_OFF_TU
- " bytes are left for transfer\n", (curl_off_t)chunk,
- size - chunk);
+ infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
+ " bytes are left for transfer\n", chunk, size - chunk);
/* Have we used the entire cache or just part of it?*/
if(pp->cache_size > chunk) {
@@ -1466,9 +1477,10 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && !imap->custom &&
- (imap->uid || data->set.upload ||
+ (imap->uid || imap->mindex || data->set.upload ||
data->set.mimepost.kind != MIMEKIND_NONE)) {
/* Handle responses after FETCH or APPEND transfer has finished */
+
if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
state(conn, IMAP_FETCH_FINAL);
else {
@@ -1492,6 +1504,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
Curl_safefree(imap->mailbox);
Curl_safefree(imap->uidvalidity);
Curl_safefree(imap->uid);
+ Curl_safefree(imap->mindex);
Curl_safefree(imap->section);
Curl_safefree(imap->partial);
Curl_safefree(imap->query);
@@ -1545,14 +1558,14 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
else if(imap->custom && (selected || !imap->mailbox))
/* Custom command using the same mailbox or no mailbox */
result = imap_perform_list(conn);
- else if(!imap->custom && selected && imap->uid)
+ else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
result = imap_perform_fetch(conn);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
result = imap_perform_search(conn);
else if(imap->mailbox && !selected &&
- (imap->custom || imap->uid || imap->query))
+ (imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
result = imap_perform_select(conn);
else
@@ -1704,8 +1717,6 @@ static CURLcode imap_regular_transfer(struct connectdata *conn,
static CURLcode imap_setup_connection(struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
-
/* Initialise the IMAP layer */
CURLcode result = imap_init(conn);
if(result)
@@ -1713,7 +1724,6 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
/* Clear the TLS upgraded flag */
conn->tls_upgraded = FALSE;
- data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
@@ -1946,7 +1956,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
- const char *begin = data->state.path;
+ const char *begin = &data->state.up.path[1]; /* skip leading slash */
const char *ptr = begin;
/* See how much of the URL is a valid path and decode it */
@@ -2018,6 +2028,13 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
imap->uid = value;
value = NULL;
}
+ else if(strcasecompare(name, "MAILINDEX") && !imap->mindex) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->mindex = value;
+ value = NULL;
+ }
else if(strcasecompare(name, "SECTION") && !imap->section) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
@@ -2045,17 +2062,10 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
/* Does the URL contain a query parameter? Only valid when we have a mailbox
and no UID as per RFC-5092 */
- if(imap->mailbox && !imap->uid && *ptr == '?') {
- /* Find the length of the query parameter */
- begin = ++ptr;
- while(imap_is_bchar(*ptr))
- ptr++;
-
- /* Decode the query parameter */
- result = Curl_urldecode(data, begin, ptr - begin, &imap->query, NULL,
- TRUE);
- if(result)
- return result;
+ if(imap->mailbox && !imap->uid && !imap->mindex) {
+ /* Get the query parameter, URL decoded */
+ (void)curl_url_get(data->state.uh, CURLUPART_QUERY, &imap->query,
+ CURLU_URLDECODE);
}
/* Any extra stuff at the end of the URL is an error */
diff --git a/Utilities/cmcurl/lib/imap.h b/Utilities/cmcurl/lib/imap.h
index 9fc4ff5a3..0efcfd293 100644
--- a/Utilities/cmcurl/lib/imap.h
+++ b/Utilities/cmcurl/lib/imap.h
@@ -58,6 +58,7 @@ struct IMAP {
char *mailbox; /* Mailbox to select */
char *uidvalidity; /* UIDVALIDITY to check in select */
char *uid; /* Message UID to fetch */
+ char *mindex; /* Index in mail box of mail to fetch */
char *section; /* Message SECTION to fetch */
char *partial; /* Message PARTIAL to fetch */
char *query; /* Query to search for */
diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c
index fb91a505d..ac5d2d4d6 100644
--- a/Utilities/cmcurl/lib/inet_ntop.c
+++ b/Utilities/cmcurl/lib/inet_ntop.c
@@ -49,7 +49,7 @@
*/
static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
{
- char tmp[sizeof "255.255.255.255"];
+ char tmp[sizeof("255.255.255.255")];
size_t len;
DEBUGASSERT(size >= 16);
diff --git a/Utilities/cmcurl/lib/inet_ntop.h b/Utilities/cmcurl/lib/inet_ntop.h
index 9f4461271..d150bb693 100644
--- a/Utilities/cmcurl/lib/inet_ntop.h
+++ b/Utilities/cmcurl/lib/inet_ntop.h
@@ -35,4 +35,3 @@ char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
#endif
#endif /* HEADER_CURL_INET_NTOP_H */
-
diff --git a/Utilities/cmcurl/lib/inet_pton.h b/Utilities/cmcurl/lib/inet_pton.h
index e216f4efa..0209b9b7b 100644
--- a/Utilities/cmcurl/lib/inet_pton.h
+++ b/Utilities/cmcurl/lib/inet_pton.h
@@ -37,4 +37,3 @@ int Curl_inet_pton(int, const char *, void *);
#endif
#endif /* HEADER_CURL_INET_PTON_H */
-
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 59c0d71a8..147ab024e 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -206,7 +206,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
if(maj != GSS_S_COMPLETE) {
gss_release_name(&min, &gssname);
if(service == srv_host) {
- Curl_failf(data, "Error importing service name %s@%s", service, host);
+ failf(data, "Error importing service name %s@%s", service, host);
return AUTH_ERROR;
}
service = srv_host;
@@ -265,6 +265,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
result = CURLE_OUT_OF_MEMORY;
free(p);
+ free(cmd);
if(result) {
ret = -2;
@@ -290,8 +291,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
(unsigned char **)&_gssresp.value,
&_gssresp.length);
if(result) {
- Curl_failf(data, "base64-decoding: %s",
- curl_easy_strerror(result));
+ failf(data, "base64-decoding: %s", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
break;
}
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 89047bcbd..ceaa71d08 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.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,15 +54,6 @@
# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
#endif
-/* These are macros in both <wincrypt.h> (in above <winldap.h>) and typedefs
- * in BoringSSL's <openssl/x509.h>
- */
-#ifdef HAVE_BORINGSSL
-# undef X509_NAME
-# undef X509_CERT_PAIR
-# undef X509_EXTENSIONS
-#endif
-
#include "urldata.h"
#include <curl/curl.h>
#include "sendf.h"
@@ -483,7 +474,13 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#endif
}
if(rc != 0) {
- failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
+#ifdef USE_WIN32_LDAP
+ failf(data, "LDAP local: bind via ldap_win_bind %s",
+ ldap_err2string(rc));
+#else
+ failf(data, "LDAP local: bind via ldap_simple_bind_s %s",
+ ldap_err2string(rc));
+#endif
result = CURLE_LDAP_CANNOT_BIND;
goto quit;
}
@@ -847,9 +844,9 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
size_t i;
if(!conn->data ||
- !conn->data->state.path ||
- conn->data->state.path[0] != '/' ||
- !checkprefix("LDAP", conn->data->change.url))
+ !conn->data->state.up.path ||
+ conn->data->state.up.path[0] != '/' ||
+ !strcasecompare("LDAP", conn->data->state.up.scheme))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -857,7 +854,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
ludp->lud_host = conn->host.name;
/* Duplicate the path */
- p = path = strdup(conn->data->state.path + 1);
+ p = path = strdup(conn->data->state.up.path + 1);
if(!path)
return LDAP_NO_MEMORY;
diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h
index 6b644b99c..b9d4c89a9 100644
--- a/Utilities/cmcurl/lib/llist.h
+++ b/Utilities/cmcurl/lib/llist.h
@@ -51,4 +51,3 @@ void Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
struct curl_llist *, struct curl_llist_element *);
#endif /* HEADER_CURL_LLIST_H */
-
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 2bb7dcc25..d35060216 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -3,7 +3,7 @@
* MD4 Message-Digest Algorithm (RFC 1320).
*
* Homepage:
- http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
+ https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index 3096602b7..45f45bbd9 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -177,7 +177,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
- http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
@@ -484,29 +484,35 @@ 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. */
- (HMAC_hupdate_func) MD5_Update, /* Hash update function. */
- (HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */
- sizeof(MD5_CTX), /* Size of hash context structure. */
- 64, /* Maximum key length. */
- 16 /* Result size. */
+ /* Hash initialization function. */
+ CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init),
+ /* Hash update function. */
+ CURLX_FUNCTION_CAST(HMAC_hupdate_func, MD5_Update),
+ /* Hash computation end function. */
+ CURLX_FUNCTION_CAST(HMAC_hfinal_func, MD5_Final),
+ /* Size of hash context structure. */
+ sizeof(MD5_CTX),
+ /* Maximum key length. */
+ 64,
+ /* Result size. */
+ 16
}
};
const MD5_params Curl_DIGEST_MD5[] = {
{
- (Curl_MD5_init_func) MD5_Init, /* Digest initialization function */
- (Curl_MD5_update_func) MD5_Update, /* Digest update function */
- (Curl_MD5_final_func) MD5_Final, /* Digest computation end function */
- sizeof(MD5_CTX), /* Size of digest context struct */
- 16 /* Result size */
+ /* Digest initialization function */
+ CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init),
+ /* Digest update function */
+ CURLX_FUNCTION_CAST(Curl_MD5_update_func, MD5_Update),
+ /* Digest computation end function */
+ CURLX_FUNCTION_CAST(Curl_MD5_final_func, MD5_Final),
+ /* Size of digest context struct */
+ sizeof(MD5_CTX),
+ /* Result size */
+ 16
}
};
@@ -527,7 +533,7 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
MD5_context *ctxt;
/* Create MD5 context */
- ctxt = malloc(sizeof *ctxt);
+ ctxt = malloc(sizeof(*ctxt));
if(!ctxt)
return ctxt;
diff --git a/Utilities/cmcurl/lib/memdebug.h b/Utilities/cmcurl/lib/memdebug.h
index 6fb8b6851..233de65a4 100644
--- a/Utilities/cmcurl/lib/memdebug.h
+++ b/Utilities/cmcurl/lib/memdebug.h
@@ -8,7 +8,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
@@ -137,13 +137,6 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
#endif
#endif /* HAVE_GETADDRINFO */
-#ifdef HAVE_GETNAMEINFO
-#undef getnameinfo
-#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
- curl_dogetnameinfo(sa, salen, host, hostlen, serv, servlen, flags, \
- __LINE__, __FILE__)
-#endif /* HAVE_GETNAMEINFO */
-
#ifdef HAVE_FREEADDRINFO
#undef freeaddrinfo
#define freeaddrinfo(data) \
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index 4c0d2eeba..ca492d11a 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -505,9 +505,6 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
mime_encoder_state *st = &part->encstate;
char *ptr = buffer;
size_t cursize = 0;
- int i;
- size_t len;
- size_t consumed;
int softlinebreak;
char buf[4];
@@ -516,9 +513,9 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
character constants that can be interpreted as non-ascii on some
platforms. Preserve ASCII encoding on output too. */
while(st->bufbeg < st->bufend) {
- len = 1;
- consumed = 1;
- i = st->buf[st->bufbeg];
+ size_t len = 1;
+ size_t consumed = 1;
+ int i = st->buf[st->bufbeg];
buf[0] = (char) i;
buf[1] = aschex[(i >> 4) & 0xF];
buf[2] = aschex[i & 0xF];
@@ -787,10 +784,10 @@ static size_t read_encoded_part_content(curl_mimepart *part,
st->bufbeg = 0;
st->bufend = len;
}
- if(st->bufend >= sizeof st->buf)
+ if(st->bufend >= sizeof(st->buf))
return cursize? cursize: READ_ERROR; /* Buffer full. */
sz = read_part_content(part, st->buf + st->bufend,
- sizeof st->buf - st->bufend);
+ sizeof(st->buf) - st->bufend);
switch(sz) {
case 0:
ateof = TRUE;
@@ -813,8 +810,6 @@ static size_t readback_part(curl_mimepart *part,
char *buffer, size_t bufsize)
{
size_t cursize = 0;
- size_t sz;
- struct curl_slist *hdr;
#ifdef CURL_DOES_CONVERSIONS
char *convbuf = buffer;
#endif
@@ -822,8 +817,8 @@ static size_t readback_part(curl_mimepart *part,
/* Readback from part. */
while(bufsize) {
- sz = 0;
- hdr = (struct curl_slist *) part->state.ptr;
+ size_t sz = 0;
+ struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
switch(part->state.state) {
case MIMESTATE_BEGIN:
mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
@@ -918,8 +913,6 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
{
curl_mime *mime = (curl_mime *) instream;
size_t cursize = 0;
- size_t sz;
- curl_mimepart *part;
#ifdef CURL_DOES_CONVERSIONS
char *convbuf = buffer;
#endif
@@ -927,8 +920,8 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
(void) size; /* Always 1. */
while(nitems) {
- sz = 0;
- part = mime->state.ptr;
+ size_t sz = 0;
+ curl_mimepart *part = mime->state.ptr;
switch(mime->state.state) {
case MIMESTATE_BEGIN:
case MIMESTATE_BODY:
@@ -1044,7 +1037,6 @@ static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
curl_mime *mime = (curl_mime *) instream;
curl_mimepart *part;
int result = CURL_SEEKFUNC_OK;
- int res;
if(whence != SEEK_SET || offset)
return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */
@@ -1053,7 +1045,7 @@ static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
return CURL_SEEKFUNC_OK; /* Already rewound. */
for(part = mime->firstpart; part; part = part->nextpart) {
- res = mime_part_rewind(part);
+ int res = mime_part_rewind(part);
if(res != CURL_SEEKFUNC_OK)
result = res;
}
@@ -1220,7 +1212,7 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
{
curl_mime *mime;
- mime = (curl_mime *) malloc(sizeof *mime);
+ mime = (curl_mime *) malloc(sizeof(*mime));
if(mime) {
mime->easy = easy;
@@ -1236,8 +1228,13 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
}
memset(mime->boundary, '-', 24);
- Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
- MIME_RAND_BOUNDARY_CHARS + 1);
+ if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+ MIME_RAND_BOUNDARY_CHARS + 1)) {
+ /* failed to get random separator, bail out */
+ free(mime->boundary);
+ free(mime);
+ return NULL;
+ }
mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
}
@@ -1247,7 +1244,7 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
/* Initialize a mime part. */
void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
{
- memset((char *) part, 0, sizeof *part);
+ memset((char *) part, 0, sizeof(*part));
part->easy = easy;
mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
}
@@ -1260,7 +1257,7 @@ curl_mimepart *curl_mime_addpart(curl_mime *mime)
if(!mime)
return NULL;
- part = (curl_mimepart *) malloc(sizeof *part);
+ part = (curl_mimepart *) malloc(sizeof(*part));
if(part) {
Curl_mime_initpart(part, mime->easy);
@@ -1349,7 +1346,6 @@ CURLcode curl_mime_data(curl_mimepart *part,
CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
{
CURLcode result = CURLE_OK;
- char *base;
if(!part)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1357,6 +1353,7 @@ CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
cleanup_part_content(part);
if(filename) {
+ char *base;
struct_stat sbuf;
if(stat(filename, &sbuf) || access(filename, R_OK))
@@ -1564,7 +1561,6 @@ static size_t slist_size(struct curl_slist *s,
static curl_off_t multipart_size(curl_mime *mime)
{
curl_off_t size;
- curl_off_t sz;
size_t boundarysize;
curl_mimepart *part;
@@ -1575,7 +1571,7 @@ static curl_off_t multipart_size(curl_mime *mime)
size = boundarysize; /* Final boundary - CRLF after headers. */
for(part = mime->firstpart; part; part = part->nextpart) {
- sz = Curl_mime_size(part);
+ curl_off_t sz = Curl_mime_size(part);
if(sz < 0)
size = sz;
@@ -1643,8 +1639,6 @@ static CURLcode add_content_type(struct curl_slist **slp,
const char *Curl_mime_contenttype(const char *filename)
{
- unsigned int i;
-
/*
* If no content type was specified, we scan through a few well-known
* extensions and pick the first we match!
@@ -1669,8 +1663,9 @@ const char *Curl_mime_contenttype(const char *filename)
if(filename) {
size_t len1 = strlen(filename);
const char *nameend = filename + len1;
+ unsigned int i;
- for(i = 0; i < sizeof ctts / sizeof ctts[0]; i++) {
+ for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) {
size_t len2 = strlen(ctts[i].extension);
if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index f85284695..0db2a9730 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -31,6 +31,7 @@
#include "progress.h"
#include "easyif.h"
#include "share.h"
+#include "psl.h"
#include "multiif.h"
#include "sendf.h"
#include "timeval.h"
@@ -68,8 +69,8 @@
#define GOOD_MULTI_HANDLE(x) \
((x) && (x)->type == CURL_MULTI_HANDLE)
-static void singlesocket(struct Curl_multi *multi,
- struct Curl_easy *data);
+static CURLMcode singlesocket(struct Curl_multi *multi,
+ struct Curl_easy *data);
static int update_timer(struct Curl_multi *multi);
static CURLMcode add_next_timeout(struct curltime now,
@@ -106,6 +107,16 @@ static const char * const statename[]={
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
+static void Curl_init_completed(struct Curl_easy *data)
+{
+ /* this is a completed transfer */
+
+ /* Important: reset the conn pointer so that we don't point to memory
+ that could be freed anytime */
+ data->easy_conn = NULL;
+ Curl_expire_clear(data); /* stop all timers */
+}
+
/* always use this function to change state, to make debugging easier */
static void mstate(struct Curl_easy *data, CURLMstate state
#ifdef DEBUGBUILD
@@ -115,17 +126,25 @@ static void mstate(struct Curl_easy *data, CURLMstate state
{
CURLMstate oldstate = data->mstate;
static const init_multistate_func finit[CURLM_STATE_LAST] = {
- NULL,
- NULL,
+ NULL, /* INIT */
+ NULL, /* CONNECT_PEND */
Curl_init_CONNECT, /* CONNECT */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- Curl_connect_free /* DO */
- /* the rest is NULL too */
+ NULL, /* WAITRESOLVE */
+ NULL, /* WAITCONNECT */
+ NULL, /* WAITPROXYCONNECT */
+ NULL, /* SENDPROTOCONNECT */
+ NULL, /* PROTOCONNECT */
+ NULL, /* WAITDO */
+ Curl_connect_free, /* DO */
+ NULL, /* DOING */
+ NULL, /* DO_MORE */
+ NULL, /* DO_DONE */
+ NULL, /* WAITPERFORM */
+ NULL, /* PERFORM */
+ NULL, /* TOOFAST */
+ NULL, /* DONE */
+ Curl_init_completed, /* COMPLETED */
+ NULL /* MSGSENT */
};
#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -328,6 +347,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_llist_init(&multi->pending, multi_freeamsg);
multi->max_pipeline_length = 5;
+ multi->pipelining = CURLPIPE_MULTIPLEX;
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
@@ -409,6 +429,14 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
else
data->state.conn_cache = &multi->conn_cache;
+#ifdef USE_LIBPSL
+ /* Do the same for PSL. */
+ if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
+ data->psl = &data->share->psl;
+ else
+ data->psl = &multi->psl;
+#endif
+
/* This adds the new entry at the 'end' of the doubly-linked circular
list of Curl_easy structs to try and maintain a FIFO queue so
the pipelined requests are in order. */
@@ -449,7 +477,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
happens if the lastcall time is set to the same time when the handle is
removed as when the next handle is added, as then the check in
update_timer() that prevents calling the application multiple times with
- the same timer infor will not trigger and then the new handle's timeout
+ the same timer info will not trigger and then the new handle's timeout
will not be notified to the app.
The work-around is thus simply to clear the 'lastcall' variable to force
@@ -464,6 +492,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
data->state.conn_cache->closure_handle->set.server_response_timeout =
data->set.server_response_timeout;
+ data->state.conn_cache->closure_handle->set.no_signal =
+ data->set.no_signal;
update_timer(multi);
return CURLM_OK;
@@ -506,13 +536,16 @@ static CURLcode multi_done(struct connectdata **connp,
/* Stop if multi_done() has already been called */
return CURLE_OK;
+ if(data->mstate == CURLM_STATE_WAITRESOLVE) {
+ /* still waiting for the resolve to complete */
+ (void)Curl_resolver_wait_resolv(conn, NULL);
+ }
+
Curl_getoff_all_pipelines(data, conn);
/* Cleanup possible redirect junk */
- free(data->req.newurl);
- data->req.newurl = NULL;
- free(data->req.location);
- data->req.location = NULL;
+ Curl_safefree(data->req.newurl);
+ Curl_safefree(data->req.location);
switch(status) {
case CURLE_ABORTED_BY_CALLBACK:
@@ -546,7 +579,7 @@ static CURLcode multi_done(struct connectdata **connp,
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 %d/%d, "
+ DEBUGF(infof(data, "Connection still in use %zu/%zu, "
"no more multi_done now!\n",
conn->send_pipe.size, conn->recv_pipe.size));
return CURLE_OK;
@@ -560,6 +593,7 @@ static CURLcode multi_done(struct connectdata **connp,
conn->dns_entry = NULL;
}
Curl_hostcache_prune(data);
+ Curl_safefree(data->state.ulbuf);
/* if the transfer was completed in a paused state there can be buffered
data left to free */
@@ -590,7 +624,7 @@ static CURLcode multi_done(struct connectdata **connp,
#endif
) || conn->bits.close
|| (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
- CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
+ CURLcode res2 = Curl_disconnect(data, conn, premature);
/* If we had an error already, make sure we return that one. But
if we got a new error, return that. */
@@ -608,7 +642,7 @@ static CURLcode multi_done(struct connectdata **connp,
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname);
- /* the connection is no longer in use */
+ /* the connection is no longer in use by this transfer */
if(Curl_conncache_return_conn(conn)) {
/* remember the most recently used connection */
data->state.lastconnect = conn;
@@ -623,7 +657,6 @@ static CURLcode multi_done(struct connectdata **connp,
cache here, and therefore cannot be used from this point on
*/
Curl_free_request_state(data);
-
return result;
}
@@ -698,6 +731,11 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
Curl_getoff_all_pipelines(data, data->easy_conn);
}
+ if(data->connect_queue.ptr)
+ /* the handle was in the pending list waiting for an available connection,
+ so go ahead and remove it */
+ Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache, *after* the possible
multi_done() call above */
@@ -727,6 +765,12 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
data->easy_conn = NULL;
}
+#ifdef USE_LIBPSL
+ /* Remove the PSL association. */
+ if(data->psl == &multi->psl)
+ data->psl = NULL;
+#endif
+
data->multi = NULL; /* clear the association to this multi handle */
/* make sure there's no pending message in the queue sent from this easy
@@ -831,12 +875,10 @@ static int multi_getsock(struct Curl_easy *data,
of sockets */
int numsocks)
{
- /* If the pipe broke, or if there's no connection left for this easy handle,
- then we MUST bail out now with no bitmask set. The no connection case can
- happen when this is called from curl_multi_remove_handle() =>
- singlesocket() => multi_getsock().
+ /* The no connection case can happen when this is called from
+ curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
- if(data->state.pipe_broke || !data->easy_conn)
+ if(!data->easy_conn)
return 0;
if(data->mstate > CURLM_STATE_CONNECT &&
@@ -863,7 +905,7 @@ static int multi_getsock(struct Curl_easy *data,
return 0;
case CURLM_STATE_WAITRESOLVE:
- return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
+ return Curl_resolv_getsock(data->easy_conn, socks, numsocks);
case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT:
@@ -902,7 +944,6 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
struct Curl_easy *data;
int this_max_fd = -1;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
- int bitmap;
int i;
(void)exc_fd_set; /* not used */
@@ -914,7 +955,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
data = multi->easyp;
while(data) {
- bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+ int bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
@@ -968,13 +1009,6 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
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! */
- (void)multi_timeout(multi, &timeout_internal);
- if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
- timeout_ms = (int)timeout_internal;
-
/* Count up how many fds we have from the multi handle */
data = multi->easyp;
while(data) {
@@ -999,6 +1033,13 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
data = data->next; /* check next handle */
}
+ /* 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! */
+ (void)multi_timeout(multi, &timeout_internal);
+ if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
+ timeout_ms = (int)timeout_internal;
+
curlfds = nfds; /* number of internal file descriptors */
nfds += extra_nfds; /* add the externally provided ones */
@@ -1068,8 +1109,6 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
int pollrc;
/* wait... */
pollrc = Curl_poll(ufds, nfds, timeout_ms);
- DEBUGF(infof(data, "Curl_poll(%d ds, %d ms) == %d\n",
- nfds, timeout_ms, pollrc));
if(pollrc > 0) {
retcode = pollrc;
@@ -1196,7 +1235,7 @@ static CURLcode multi_reconnect_request(struct connectdata **connp)
return result;
/* Resolved, continue with the connection */
- result = Curl_async_resolved(conn, &protocol_done);
+ result = Curl_once_resolved(conn, &protocol_done);
if(result)
return result;
}
@@ -1312,24 +1351,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
bool stream_error = FALSE;
rc = CURLM_OK;
- /* Handle the case when the pipe breaks, i.e., the connection
- we're using gets cleaned up and we're left with nothing. */
- if(data->state.pipe_broke) {
- infof(data, "Pipe broke: handle %p, url = %s\n",
- (void *)data, data->state.path);
-
- if(data->mstate < CURLM_STATE_COMPLETED) {
- /* Head back to the CONNECT state */
- multistate(data, CURLM_STATE_CONNECT);
- rc = CURLM_CALL_MULTI_PERFORM;
- result = CURLE_OK;
- }
-
- data->state.pipe_broke = FALSE;
- data->easy_conn = NULL;
- continue;
- }
-
if(!data->easy_conn &&
data->mstate > CURLM_STATE_CONNECT &&
data->mstate < CURLM_STATE_DONE) {
@@ -1490,7 +1511,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(!dns)
- result = Curl_resolver_is_resolved(data->easy_conn, &dns);
+ result = Curl_resolv_check(data->easy_conn, &dns);
/* Update sockets here, because the socket(s) may have been
closed and the application thus needs to be told, even if it
@@ -1503,10 +1524,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
- result = Curl_async_resolved(data->easy_conn, &protocol_connect);
+ result = Curl_once_resolved(data->easy_conn, &protocol_connect);
if(result)
- /* if Curl_async_resolved() returns failure, the connection struct
+ /* if Curl_once_resolved() returns failure, the connection struct
is already freed and gone */
data->easy_conn = NULL; /* no more connection */
else {
@@ -1555,6 +1576,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
}
}
+ else if(result)
+ stream_error = TRUE;
break;
#endif
@@ -1585,7 +1608,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_SENDPROTOCONNECT:
result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
- if(!protocol_connect)
+ if(!result && !protocol_connect)
/* switch to waiting state */
multistate(data, CURLM_STATE_PROTOCONNECT);
else if(!result) {
@@ -1684,7 +1707,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
char *newurl = NULL;
followtype follow = FOLLOW_NONE;
CURLcode drc;
- bool retry = FALSE;
drc = Curl_retry_request(data->easy_conn, &newurl);
if(drc) {
@@ -1692,15 +1714,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = drc;
stream_error = TRUE;
}
- else
- retry = (newurl)?TRUE:FALSE;
Curl_posttransfer(data);
drc = multi_done(&data->easy_conn, result, FALSE);
/* When set to retry the connection, we must to go back to
* the CONNECT state */
- if(retry) {
+ if(newurl) {
if(!drc || (drc == CURLE_SEND_ERROR)) {
follow = FOLLOW_RETRY;
drc = Curl_follow(data, newurl, follow);
@@ -1909,6 +1929,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
if(!ret)
retry = (newurl)?TRUE:FALSE;
+ else if(!result)
+ result = ret;
if(retry) {
/* if we are to retry, set the result to OK and consider the
@@ -1968,6 +1990,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = CURLM_CALL_MULTI_PERFORM;
}
}
+ free(newurl);
}
else {
/* after the transfer is done, go DONE */
@@ -1979,18 +2002,21 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
newurl = data->req.location;
data->req.location = NULL;
result = Curl_follow(data, newurl, FOLLOW_FAKE);
- if(result)
+ free(newurl);
+ if(result) {
stream_error = TRUE;
+ result = multi_done(&data->easy_conn, result, TRUE);
+ }
}
- multistate(data, CURLM_STATE_DONE);
- rc = CURLM_CALL_MULTI_PERFORM;
+ if(!result) {
+ multistate(data, CURLM_STATE_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
}
}
else if(comeback)
rc = CURLM_CALL_MULTI_PERFORM;
-
- free(newurl);
break;
}
@@ -2040,16 +2066,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
case CURLM_STATE_COMPLETED:
- /* this is a completed transfer, it is likely to still be connected */
-
- /* This node should be delinked from the list now and we should post
- an information message that we are complete. */
-
- /* Important: reset the conn pointer so that we don't point to memory
- that could be freed anytime */
- data->easy_conn = NULL;
-
- Curl_expire_clear(data); /* stop all timers */
break;
case CURLM_STATE_MSGSENT:
@@ -2071,8 +2087,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* NOTE: no attempt to disconnect connections must be made
in the case blocks above - cleanup happens only here */
- data->state.pipe_broke = FALSE;
-
/* Check if we can move pending requests to send pipe */
process_pending_handles(multi); /* connection */
@@ -2087,7 +2101,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Don't attempt to send data over a connection that timed out */
bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
/* disconnect properly */
- Curl_disconnect(data->easy_conn, dead_connection);
+ Curl_disconnect(data, data->easy_conn, dead_connection);
/* This is where we make sure that the easy_conn pointer is reset.
We don't have to do this in every case block above where a
@@ -2101,6 +2115,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
multistate(data, CURLM_STATE_COMPLETED);
+ rc = CURLM_CALL_MULTI_PERFORM;
}
/* if there's still a connection to use, call the progress function */
else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
@@ -2117,22 +2132,26 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(CURLM_STATE_COMPLETED == data->mstate) {
- /* now fill in the Curl_message with this info */
- msg = &data->msg;
-
- msg->extmsg.msg = CURLMSG_DONE;
- msg->extmsg.easy_handle = data;
- msg->extmsg.data.result = result;
+ if(data->set.fmultidone) {
+ /* signal via callback instead */
+ data->set.fmultidone(data, result);
+ }
+ else {
+ /* now fill in the Curl_message with this info */
+ msg = &data->msg;
- rc = multi_addmsg(multi, msg);
+ msg->extmsg.msg = CURLMSG_DONE;
+ msg->extmsg.easy_handle = data;
+ msg->extmsg.data.result = result;
+ rc = multi_addmsg(multi, msg);
+ DEBUGASSERT(!data->easy_conn);
+ }
multistate(data, CURLM_STATE_MSGSENT);
}
} while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
data->result = result;
-
-
return rc;
}
@@ -2220,6 +2239,11 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
data->state.conn_cache = NULL;
data->multi = NULL; /* clear the association */
+#ifdef USE_LIBPSL
+ if(data->psl == &multi->psl)
+ data->psl = NULL;
+#endif
+
data = nextdata;
}
@@ -2232,6 +2256,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
Curl_llist_destroy(&multi->pending, NULL);
Curl_hash_destroy(&multi->hostcache);
+ Curl_psl_destroy(&multi->psl);
/* Free the blacklists by setting them to NULL */
Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
@@ -2286,8 +2311,8 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
* and if we have a different state in any of those sockets from last time we
* call the callback accordingly.
*/
-static void singlesocket(struct Curl_multi *multi,
- struct Curl_easy *data)
+static CURLMcode singlesocket(struct Curl_multi *multi,
+ struct Curl_easy *data)
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int i;
@@ -2334,7 +2359,7 @@ static void singlesocket(struct Curl_multi *multi,
entry = sh_addentry(&multi->sockhash, s, data);
if(!entry)
/* fatal */
- return;
+ return CURLM_OUT_OF_MEMORY;
}
/* we know (entry != NULL) at this point, see the logic above */
@@ -2422,6 +2447,7 @@ static void singlesocket(struct Curl_multi *multi,
memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
data->numsocks = num;
+ return CURLM_OK;
}
void Curl_updatesocket(struct Curl_easy *data)
@@ -2442,20 +2468,23 @@ void Curl_updatesocket(struct Curl_easy *data)
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
{
- struct Curl_multi *multi = conn->data->multi;
- if(multi) {
- /* this is set if this connection is part of a handle that is added to
- a multi handle, and only then this is necessary */
- struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
-
- if(entry) {
- if(multi->socket_cb)
- multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
- multi->socket_userp,
- entry->socketp);
+ if(conn->data) {
+ /* if there's still an easy handle associated with this connection */
+ struct Curl_multi *multi = conn->data->multi;
+ if(multi) {
+ /* this is set if this connection is part of a handle that is added to
+ a multi handle, and only then this is necessary */
+ struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
+
+ if(entry) {
+ if(multi->socket_cb)
+ multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+ multi->socket_userp,
+ entry->socketp);
- /* now remove it from the socket hash */
- sh_delentry(&multi->sockhash, s);
+ /* now remove it from the socket hash */
+ sh_delentry(&multi->sockhash, s);
+ }
}
}
}
@@ -2535,8 +2564,8 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
and callbacks */
if(result != CURLM_BAD_HANDLE) {
data = multi->easyp;
- while(data) {
- singlesocket(multi, data);
+ while(data && !result) {
+ result = singlesocket(multi, data);
data = data->next;
}
}
@@ -2590,10 +2619,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* clear the bitmask only if not locked */
data->easy_conn->cselect_bits = 0;
- if(CURLM_OK >= result)
+ if(CURLM_OK >= result) {
/* get the socket(s) and check if the state has been changed since
last */
- singlesocket(multi, data);
+ result = singlesocket(multi, data);
+ if(result)
+ return result;
+ }
/* Now we fall-through and do the timer-based stuff, since we don't want
to force the user to have to deal with timeouts as long as at least
@@ -2627,10 +2659,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
result = multi_runsingle(multi, now, data);
sigpipe_restore(&pipe_st);
- if(CURLM_OK >= result)
+ if(CURLM_OK >= result) {
/* get the socket(s) and check if the state has been changed since
last */
- singlesocket(multi, data);
+ result = singlesocket(multi, data);
+ if(result)
+ return result;
+ }
}
/* Check if there's one (more) expired timer to deal with! This function
@@ -2677,7 +2712,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
multi->push_userp = va_arg(param, void *);
break;
case CURLMOPT_PIPELINING:
- multi->pipelining = va_arg(param, long);
+ multi->pipelining = va_arg(param, long) & CURLPIPE_MULTIPLEX;
break;
case CURLMOPT_TIMERFUNCTION:
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
@@ -2924,7 +2959,6 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
{
struct Curl_multi *multi = data->multi;
struct curltime *nowp = &data->state.expiretime;
- int rc;
struct curltime set;
/* this is only interesting while there is still an associated multi struct
@@ -2955,6 +2989,7 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
timediff_t diff = Curl_timediff(set, *nowp);
+ int rc;
if(diff > 0) {
/* The current splay tree entry is sooner than this new expiry time.
@@ -3000,7 +3035,6 @@ void Curl_expire_clear(struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct curltime *nowp = &data->state.expiretime;
- int rc;
/* this is only interesting while there is still an associated multi struct
remaining! */
@@ -3011,6 +3045,7 @@ void Curl_expire_clear(struct Curl_easy *data)
/* Since this is an cleared time, we must remove the previous entry from
the splay tree */
struct curl_llist *list = &data->state.timeoutlist;
+ int rc;
rc = Curl_splayremovebyaddr(multi->timetree,
&data->state.timenode,
@@ -3100,12 +3135,15 @@ static void process_pending_handles(struct Curl_multi *multi)
}
}
-void Curl_set_in_callback(struct Curl_easy *easy, bool value)
+void Curl_set_in_callback(struct Curl_easy *data, bool value)
{
- if(easy->multi_easy)
- easy->multi_easy->in_callback = value;
- else if(easy->multi)
- easy->multi->in_callback = value;
+ /* might get called when there is no data pointer! */
+ if(data) {
+ if(data->multi_easy)
+ data->multi_easy->in_callback = value;
+ else if(data->multi)
+ data->multi->in_callback = value;
+ }
}
bool Curl_is_in_callback(struct Curl_easy *easy)
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index 1a5017f4a..ea2bf352d 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.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
@@ -23,6 +23,7 @@
***************************************************************************/
#include "conncache.h"
+#include "psl.h"
struct Curl_message {
struct curl_llist_element list;
@@ -97,6 +98,11 @@ struct Curl_multi {
/* Hostname cache */
struct curl_hash hostcache;
+#ifdef USE_LIBPSL
+ /* PSL cache. */
+ struct PslCache psl;
+#endif
+
/* timetree points to the splay-tree of time nodes to figure out expire
times of all currently set timers */
struct Curl_tree *timetree;
diff --git a/Utilities/cmcurl/lib/netrc.c b/Utilities/cmcurl/lib/netrc.c
index dbcc59ac9..1724b35b0 100644
--- a/Utilities/cmcurl/lib/netrc.c
+++ b/Utilities/cmcurl/lib/netrc.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
@@ -57,7 +57,11 @@ int Curl_parsenetrc(const char *host,
{
FILE *file;
int retcode = 1;
- int specific_login = (*loginp && **loginp != 0);
+ char *login = *loginp;
+ char *password = *passwordp;
+ bool specific_login = (login && *login != 0);
+ bool login_alloc = FALSE;
+ bool password_alloc = FALSE;
bool netrc_alloc = FALSE;
enum host_lookup_state state = NOTHING;
@@ -115,7 +119,7 @@ int Curl_parsenetrc(const char *host,
char *tok;
char *tok_buf;
bool done = FALSE;
- char netrcbuffer[256];
+ char netrcbuffer[4096];
int netrcbuffsize = (int)sizeof(netrcbuffer);
while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
@@ -125,7 +129,7 @@ int Curl_parsenetrc(const char *host,
continue;
while(!done && tok) {
- if((*loginp && **loginp) && (*passwordp && **passwordp)) {
+ if((login && *login) && (password && *password)) {
done = TRUE;
break;
}
@@ -158,26 +162,34 @@ int Curl_parsenetrc(const char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
- state_our_login = strcasecompare(*loginp, tok);
+ state_our_login = strcasecompare(login, tok);
}
else {
- free(*loginp);
- *loginp = strdup(tok);
- if(!*loginp) {
+ if(login_alloc) {
+ free(login);
+ login_alloc = FALSE;
+ }
+ login = strdup(tok);
+ if(!login) {
retcode = -1; /* allocation failed */
goto out;
}
+ login_alloc = TRUE;
}
state_login = 0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
- free(*passwordp);
- *passwordp = strdup(tok);
- if(!*passwordp) {
+ if(password_alloc) {
+ free(password);
+ password_alloc = FALSE;
+ }
+ password = strdup(tok);
+ if(!password) {
retcode = -1; /* allocation failed */
goto out;
}
+ password_alloc = TRUE;
}
state_password = 0;
}
@@ -198,6 +210,24 @@ int Curl_parsenetrc(const char *host,
} /* while fgets() */
out:
+ if(!retcode) {
+ if(login_alloc) {
+ if(*loginp)
+ free(*loginp);
+ *loginp = login;
+ }
+ if(password_alloc) {
+ if(*passwordp)
+ free(*passwordp);
+ *passwordp = password;
+ }
+ }
+ else {
+ if(login_alloc)
+ free(login);
+ if(password_alloc)
+ free(password);
+ }
fclose(file);
}
diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c
index 5959281e5..4d105c1fe 100644
--- a/Utilities/cmcurl/lib/nonblock.c
+++ b/Utilities/cmcurl/lib/nonblock.c
@@ -48,7 +48,8 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */)
{
#if defined(USE_BLOCKING_SOCKETS)
-
+ (void)sockfd;
+ (void)nonblock;
return 0; /* returns success */
#elif defined(HAVE_FCNTL_O_NONBLOCK)
diff --git a/Utilities/cmcurl/lib/nonblock.h b/Utilities/cmcurl/lib/nonblock.h
index 98cdc25ab..eb18ea1c3 100644
--- a/Utilities/cmcurl/lib/nonblock.h
+++ b/Utilities/cmcurl/lib/nonblock.h
@@ -28,4 +28,3 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */);
#endif /* HEADER_CURL_NONBLOCK_H */
-
diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index 215d933ac..7bf5f51c3 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.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
@@ -195,7 +195,7 @@ int GetOrSetUpData(int id, libdata_t **appData,
if(!app_data->tenbytes || !app_data->lock) {
if(app_data->lock)
NXMutexFree(app_data->lock);
-
+ free(app_data->tenbytes);
free(app_data);
app_data = (libdata_t *) NULL;
err = ENOMEM;
@@ -213,6 +213,9 @@ int GetOrSetUpData(int id, libdata_t **appData,
err = set_app_data(gLibId, app_data);
if(err) {
+ if(app_data->lock)
+ NXMutexFree(app_data->lock);
+ free(app_data->tenbytes);
free(app_data);
app_data = (libdata_t *) NULL;
err = ENOMEM;
diff --git a/Utilities/cmcurl/lib/parsedate.h b/Utilities/cmcurl/lib/parsedate.h
index 2e59eb17c..8dc3b90ec 100644
--- a/Utilities/cmcurl/lib/parsedate.h
+++ b/Utilities/cmcurl/lib/parsedate.h
@@ -28,4 +28,3 @@ extern const char * const Curl_month[12];
CURLcode Curl_gmtime(time_t intime, struct tm *store);
#endif /* HEADER_CURL_PARSEDATE_H */
-
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index ad370ee82..2e93d201f 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.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,7 +49,6 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
struct connectdata *conn = pp->conn;
struct Curl_easy *data = conn->data;
time_t timeout_ms; /* in milliseconds */
- time_t timeout2_ms; /* in milliseconds */
long response_time = (data->set.server_response_timeout)?
data->set.server_response_timeout: pp->response_time;
@@ -65,7 +64,7 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
if(data->set.timeout) {
/* if timeout is requested, find out how much remaining time we have */
- timeout2_ms = data->set.timeout - /* timeout time */
+ time_t timeout2_ms = data->set.timeout - /* timeout time */
Curl_timediff(Curl_now(), conn->now); /* spent time */
/* pick the lowest number */
@@ -222,8 +221,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
}
if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT,
- s, (size_t)bytes_written, conn);
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
if(bytes_written != (ssize_t)write_len) {
/* the whole chunk was not sent, keep it around and adjust sizes */
@@ -371,7 +369,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#endif
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- pp->linestart_resp, (size_t)perline, conn);
+ pp->linestart_resp, (size_t)perline);
/*
* We pass all response-lines to the callback function registered
diff --git a/Utilities/cmcurl/lib/pipeline.c b/Utilities/cmcurl/lib/pipeline.c
index 4d41b0413..8de3babd7 100644
--- a/Utilities/cmcurl/lib/pipeline.c
+++ b/Utilities/cmcurl/lib/pipeline.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2013 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 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
@@ -82,7 +82,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data,
penalized = TRUE;
infof(data, "Conn: %ld (%p) Receive pipe weight: (%"
- CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n",
+ CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T
+ "), penalized: %s\n",
conn->connection_id, (void *)conn, recv_size,
conn->chunk.datasize, penalized?"TRUE":"FALSE");
return penalized;
@@ -109,8 +110,8 @@ CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
pipeline = &conn->send_pipe;
result = addHandleToPipeline(handle, pipeline);
-
- if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) {
+ if((conn->bundle->multiuse == BUNDLE_PIPELINING) &&
+ (pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head)) {
/* this is a new one as head, expire it */
Curl_pipeline_leave_write(conn); /* not in use yet */
Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 78f6afef1..5e0fd2299 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -613,7 +613,6 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
- size_t i;
(void)instate; /* no use for this yet */
@@ -625,6 +624,7 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
/* Does the server support APOP authentication? */
if(len >= 4 && line[len - 2] == '>') {
/* Look for the APOP timestamp */
+ size_t i;
for(i = 3; i < len - 2; ++i) {
if(line[i] == '<') {
/* Calculate the length of the timestamp */
@@ -664,7 +664,6 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
- size_t wordlen;
(void)instate; /* no use for this yet */
@@ -689,6 +688,7 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
/* Loop through the data line */
for(;;) {
size_t llen;
+ size_t wordlen;
unsigned int mechbit;
while(len &&
@@ -1303,8 +1303,6 @@ static CURLcode pop3_regular_transfer(struct connectdata *conn,
static CURLcode pop3_setup_connection(struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
-
/* Initialise the POP3 layer */
CURLcode result = pop3_init(conn);
if(result)
@@ -1312,7 +1310,6 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
/* Clear the TLS upgraded flag */
conn->tls_upgraded = FALSE;
- data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
@@ -1387,7 +1384,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
/* The POP3 struct is already initialised in pop3_connect() */
struct Curl_easy *data = conn->data;
struct POP3 *pop3 = data->req.protop;
- const char *path = data->state.path;
+ const char *path = &data->state.up.path[1]; /* skip leading path */
/* URL decode the path for the message ID */
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index f59faa3d3..a94668dc2 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -35,22 +35,22 @@
byte) */
static void time2str(char *r, curl_off_t seconds)
{
- curl_off_t d, h, m, s;
+ curl_off_t h;
if(seconds <= 0) {
strcpy(r, "--:--:--");
return;
}
h = seconds / CURL_OFF_T_C(3600);
if(h <= CURL_OFF_T_C(99)) {
- m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
- s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
+ curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
+ curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
}
else {
/* this equals to more than 99 hours, switch to a more suitable output
format to fit within the limits. */
- d = seconds / CURL_OFF_T_C(86400);
+ curl_off_t d = seconds / CURL_OFF_T_C(86400);
h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
if(d <= CURL_OFF_T_C(999))
snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
@@ -369,25 +369,10 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
int Curl_pgrsUpdate(struct connectdata *conn)
{
struct curltime now;
- int result;
- char max5[6][10];
- curl_off_t dlpercen = 0;
- curl_off_t ulpercen = 0;
- curl_off_t total_percen = 0;
- curl_off_t total_transfer;
- curl_off_t total_expected_transfer;
curl_off_t timespent;
curl_off_t timespent_ms; /* milliseconds */
struct Curl_easy *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME;
- int checkindex;
- int countindex; /* amount of seconds stored in the speeder array */
- char time_left[10];
- char time_total[10];
- char time_spent[10];
- curl_off_t ulestimate = 0;
- curl_off_t dlestimate = 0;
- curl_off_t total_estimate;
bool shownow = FALSE;
curl_off_t dl = data->progress.downloaded;
curl_off_t ul = data->progress.uploaded;
@@ -413,6 +398,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* Calculations done at most once a second, unless end is reached */
if(data->progress.lastshow != now.tv_sec) {
+ int countindex; /* amount of seconds stored in the speeder array */
shownow = TRUE;
data->progress.lastshow = now.tv_sec;
@@ -438,6 +424,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* first of all, we don't do this if there's no counted seconds yet */
if(countindex) {
+ int checkindex;
timediff_t span_ms;
/* Get the index position to compare with the 'nowindex' position.
@@ -477,8 +464,21 @@ int Curl_pgrsUpdate(struct connectdata *conn)
if(!(data->progress.flags & PGRS_HIDE)) {
/* progress meter has not been shut off */
+ char max5[6][10];
+ curl_off_t dlpercen = 0;
+ curl_off_t ulpercen = 0;
+ curl_off_t total_percen = 0;
+ curl_off_t total_transfer;
+ curl_off_t total_expected_transfer;
+ char time_left[10];
+ char time_total[10];
+ char time_spent[10];
+ curl_off_t ulestimate = 0;
+ curl_off_t dlestimate = 0;
+ curl_off_t total_estimate;
if(data->set.fxferinfo) {
+ int result;
/* There's a callback set, call that */
Curl_set_in_callback(data, true);
result = data->set.fxferinfo(data->set.progress_client,
@@ -492,6 +492,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
return result;
}
if(data->set.fprogress) {
+ int result;
/* The older deprecated callback is set, call that */
Curl_set_in_callback(data, true);
result = data->set.fprogress(data->set.progress_client,
diff --git a/Utilities/cmcurl/lib/progress.h b/Utilities/cmcurl/lib/progress.h
index 2baa925db..3515ac6d5 100644
--- a/Utilities/cmcurl/lib/progress.h
+++ b/Utilities/cmcurl/lib/progress.h
@@ -56,23 +56,9 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
struct curltime start,
struct curltime now);
-/* Don't show progress for sizes smaller than: */
-#define LEAST_SIZE_PROGRESS BUFSIZE
-
-#define PROGRESS_DOWNLOAD (1<<0)
-#define PROGRESS_UPLOAD (1<<1)
-#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD)
-
-#define PGRS_SHOW_DL (1<<0)
-#define PGRS_SHOW_UL (1<<1)
-#define PGRS_DONE_DL (1<<2)
-#define PGRS_DONE_UL (1<<3)
#define PGRS_HIDE (1<<4)
#define PGRS_UL_SIZE_KNOWN (1<<5)
#define PGRS_DL_SIZE_KNOWN (1<<6)
-
#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
-
#endif /* HEADER_CURL_PROGRESS_H */
-
diff --git a/Utilities/cmcurl/lib/psl.c b/Utilities/cmcurl/lib/psl.c
new file mode 100644
index 000000000..568baff03
--- /dev/null
+++ b/Utilities/cmcurl/lib/psl.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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>
+
+#ifdef USE_LIBPSL
+
+#include "psl.h"
+#include "share.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+void Curl_psl_destroy(struct PslCache *pslcache)
+{
+ if(pslcache->psl) {
+ if(pslcache->dynamic)
+ psl_free((psl_ctx_t *) pslcache->psl);
+ pslcache->psl = NULL;
+ pslcache->dynamic = FALSE;
+ }
+}
+
+static time_t now_seconds(void)
+{
+ struct curltime now = Curl_now();
+
+ return now.tv_sec;
+}
+
+const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy)
+{
+ struct PslCache *pslcache = easy->psl;
+ const psl_ctx_t *psl;
+ time_t now;
+
+ if(!pslcache)
+ return NULL;
+
+ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
+ now = now_seconds();
+ if(!pslcache->psl || pslcache->expires <= now) {
+ /* Let a chance to other threads to do the job: avoids deadlock. */
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+
+ /* Update cache: this needs an exclusive lock. */
+ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE);
+
+ /* Recheck in case another thread did the job. */
+ now = now_seconds();
+ if(!pslcache->psl || pslcache->expires <= now) {
+ bool dynamic = FALSE;
+ time_t expires = TIME_T_MAX;
+
+#if defined(PSL_VERSION_NUMBER) && PSL_VERSION_NUMBER >= 0x001000
+ psl = psl_latest(NULL);
+ dynamic = psl != NULL;
+ /* Take care of possible time computation overflow. */
+ expires = now < TIME_T_MAX - PSL_TTL? now + PSL_TTL: TIME_T_MAX;
+
+ /* Only get the built-in PSL if we do not already have the "latest". */
+ if(!psl && !pslcache->dynamic)
+#endif
+
+ psl = psl_builtin();
+
+ if(psl) {
+ Curl_psl_destroy(pslcache);
+ pslcache->psl = psl;
+ pslcache->dynamic = dynamic;
+ pslcache->expires = expires;
+ }
+ }
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); /* Release exclusive lock. */
+ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
+ }
+ psl = pslcache->psl;
+ if(!psl)
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+ return psl;
+}
+
+void Curl_psl_release(struct Curl_easy *easy)
+{
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+}
+
+#endif /* USE_LIBPSL */
diff --git a/Utilities/cmcurl/lib/psl.h b/Utilities/cmcurl/lib/psl.h
new file mode 100644
index 000000000..e9f99d03e
--- /dev/null
+++ b/Utilities/cmcurl/lib/psl.h
@@ -0,0 +1,47 @@
+#ifndef HEADER_PSL_H
+#define HEADER_PSL_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.
+ *
+ ***************************************************************************/
+
+#ifdef USE_LIBPSL
+#include <libpsl.h>
+
+#define PSL_TTL (72 * 3600) /* PSL time to live before a refresh. */
+
+struct PslCache {
+ const psl_ctx_t *psl; /* The PSL. */
+ time_t expires; /* Time this PSL life expires. */
+ bool dynamic; /* PSL should be released when no longer needed. */
+};
+
+const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy);
+void Curl_psl_release(struct Curl_easy *easy);
+void Curl_psl_destroy(struct PslCache *pslcache);
+
+#else
+
+#define Curl_psl_use(easy) NULL
+#define Curl_psl_release(easy)
+#define Curl_psl_destroy(pslcache)
+
+#endif /* USE_LIBPSL */
+#endif /* HEADER_PSL_H */
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
index 0769ed151..6ee45feb1 100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.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
@@ -158,7 +158,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
DEBUGASSERT(num > 1);
#ifdef __clang_analyzer__
- /* This silences a scan-build warning about accesssing this buffer with
+ /* This silences a scan-build warning about accessing this buffer with
uninitialized memory. */
memset(buffer, 0, sizeof(buffer));
#endif
@@ -174,6 +174,8 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
return result;
while(num) {
+ /* clang-tidy warns on this line without this comment: */
+ /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
*rnd++ = hex[(*bufp & 0xF0)>>4];
*rnd++ = hex[*bufp & 0x0F];
bufp++;
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index 41f300013..01dfce640 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -218,8 +218,6 @@ static CURLcode rtsp_done(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct RTSP *rtsp = data->req.protop;
CURLcode httpStatus;
- long CSeq_sent;
- long CSeq_recv;
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
@@ -229,8 +227,8 @@ static CURLcode rtsp_done(struct connectdata *conn,
if(rtsp) {
/* Check the sequence numbers */
- CSeq_sent = rtsp->CSeq_sent;
- CSeq_recv = rtsp->CSeq_recv;
+ long CSeq_sent = rtsp->CSeq_sent;
+ long CSeq_recv = rtsp->CSeq_recv;
if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) {
failf(data,
"The CSeq of this request %ld did not match the response %ld",
@@ -464,7 +462,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return CURLE_OUT_OF_MEMORY;
result =
- Curl_add_bufferf(req_buffer,
+ Curl_add_bufferf(&req_buffer,
"%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
"CSeq: %ld\r\n", /* CSeq */
p_request, p_stream_uri, rtsp->CSeq_sent);
@@ -476,7 +474,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
* to make comparison easier
*/
if(p_session_id) {
- result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id);
+ result = Curl_add_bufferf(&req_buffer, "Session: %s\r\n", p_session_id);
if(result)
return result;
}
@@ -484,7 +482,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Shared HTTP-like options
*/
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"%s" /* transport */
"%s" /* accept */
"%s" /* accept-encoding */
@@ -543,9 +541,10 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* 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")) {
- result = Curl_add_bufferf(req_buffer,
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
- (data->set.upload ? putsize : postsize));
+ result =
+ Curl_add_bufferf(&req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
+ (data->set.upload ? putsize : postsize));
if(result)
return result;
}
@@ -553,8 +552,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(req_buffer,
- "Content-Type: text/parameters\r\n");
+ result = Curl_add_bufferf(&req_buffer,
+ "Content-Type: text/parameters\r\n");
if(result)
return result;
}
@@ -562,8 +561,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(req_buffer,
- "Content-Type: application/sdp\r\n");
+ result = Curl_add_bufferf(&req_buffer,
+ "Content-Type: application/sdp\r\n");
if(result)
return result;
}
@@ -581,19 +580,19 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* RTSP never allows chunked transfer */
data->req.forbidchunk = TRUE;
/* Finish the request buffer */
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
if(postsize > 0) {
- result = Curl_add_buffer(req_buffer, data->set.postfields,
+ result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize);
if(result)
return result;
}
/* issue the request */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
diff --git a/Utilities/cmcurl/lib/rtsp.h b/Utilities/cmcurl/lib/rtsp.h
index 8375a5317..2f9cc32c8 100644
--- a/Utilities/cmcurl/lib/rtsp.h
+++ b/Utilities/cmcurl/lib/rtsp.h
@@ -64,4 +64,3 @@ struct RTSP {
#endif /* HEADER_CURL_RTSP_H */
-
diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c
index d17198547..c278406ba 100644
--- a/Utilities/cmcurl/lib/security.c
+++ b/Utilities/cmcurl/lib/security.c
@@ -61,7 +61,9 @@
#include "strcase.h"
#include "warnless.h"
#include "strdup.h"
-/* The last #include file should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
#include "memdebug.h"
static const struct {
@@ -390,7 +392,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
if(conn->data->set.verbose) {
buf[decoded_len] = '\n';
- Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn);
+ Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
}
buf[decoded_len] = '\0';
@@ -422,7 +424,7 @@ static int sec_set_protection_level(struct connectdata *conn)
if(!conn->sec_complete) {
infof(conn->data, "Trying to change the protection level after the"
- "completion of the data exchange.\n");
+ " completion of the data exchange.\n");
return -1;
}
@@ -488,7 +490,7 @@ static CURLcode choose_mech(struct connectdata *conn)
tmp_allocation = realloc(conn->app_data, mech->size);
if(tmp_allocation == NULL) {
- failf(data, "Failed realloc of size %u", mech->size);
+ failf(data, "Failed realloc of size %zu", mech->size);
mech = NULL;
return CURLE_OUT_OF_MEMORY;
}
diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index 0406dd26a..6e7389015 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -80,7 +80,6 @@ int Curl_wait_ms(int timeout_ms)
#endif
struct curltime initial_tv;
int pending_ms;
- int error;
#endif
int r = 0;
@@ -98,6 +97,7 @@ int Curl_wait_ms(int timeout_ms)
pending_ms = timeout_ms;
initial_tv = Curl_now();
do {
+ int error;
#if defined(HAVE_POLL_FINE)
r = poll(NULL, 0, pending_ms);
#else
@@ -160,7 +160,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
#endif
struct curltime initial_tv = {0, 0};
int pending_ms = 0;
- int error;
int r;
int ret;
@@ -210,6 +209,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
}
do {
+ int error;
if(timeout_ms < 0)
pending_ms = -1;
else if(!timeout_ms)
@@ -291,6 +291,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
do {
+ int error;
if(timeout_ms > 0) {
pending_tv.tv_sec = pending_ms / 1000;
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
@@ -402,7 +403,6 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
bool fds_none = TRUE;
unsigned int i;
int pending_ms = 0;
- int error;
int r;
if(ufds) {
@@ -431,6 +431,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
#ifdef HAVE_POLL_FINE
do {
+ int error;
if(timeout_ms < 0)
pending_ms = -1;
else if(!timeout_ms)
@@ -502,6 +503,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
do {
+ int error;
if(timeout_ms > 0) {
pending_tv.tv_sec = pending_ms / 1000;
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 4351786c3..9a1ba45a7 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -113,4 +113,3 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
#endif
#endif /* HEADER_CURL_SELECT_H */
-
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 27c0ccc73..d3c10b369 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -240,7 +240,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
va_end(ap);
len = strlen(print_buffer);
- Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
+ Curl_debug(data, CURLINFO_TEXT, print_buffer, len);
}
}
@@ -265,7 +265,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
if(data->set.verbose) {
error[len] = '\n';
error[++len] = '\0';
- Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
+ Curl_debug(data, CURLINFO_TEXT, error, len);
}
va_end(ap);
}
@@ -300,7 +300,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
break;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
if((size_t)bytes_written != write_len) {
/* if not all was written at once, we must advance the pointer, decrease
@@ -762,8 +762,8 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
}
/* return 0 on success */
-static int showit(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size)
+int Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size)
{
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
@@ -834,41 +834,3 @@ static int showit(struct Curl_easy *data, curl_infotype type,
#endif
return rc;
}
-
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size,
- struct connectdata *conn)
-{
- int rc;
- if(data->set.printhost && conn && conn->host.dispname) {
- char buffer[160];
- const char *t = NULL;
- const char *w = "Data";
- switch(type) {
- case CURLINFO_HEADER_IN:
- w = "Header";
- /* FALLTHROUGH */
- case CURLINFO_DATA_IN:
- t = "from";
- break;
- case CURLINFO_HEADER_OUT:
- w = "Header";
- /* FALLTHROUGH */
- case CURLINFO_DATA_OUT:
- t = "to";
- break;
- default:
- break;
- }
-
- if(t) {
- snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
- conn->host.dispname);
- rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
- if(rc)
- return rc;
- }
- }
- rc = showit(data, type, ptr, size);
- return rc;
-}
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index 7c9134dec..c68b017da 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -36,7 +36,7 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#elif defined(HAVE_VARIADIC_MACROS_GCC)
#define infof(x...) Curl_nop_stmt
#else
-#define infof (void)
+#error "missing VARIADIC macro define, fix and rebuild!"
#endif
#else /* CURL_DISABLE_VERBOSE_STRINGS */
@@ -84,9 +84,8 @@ CURLcode Curl_write_plain(struct connectdata *conn,
ssize_t *written);
/* the function used to output verbose information */
-int Curl_debug(struct Curl_easy *handle, curl_infotype type,
- char *data, size_t size,
- struct connectdata *conn);
+int Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size);
#endif /* HEADER_CURL_SENDF_H */
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index af53ee3ef..22956a20f 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -127,9 +127,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.dns_cache_timeout = arg;
break;
case CURLOPT_DNS_USE_GLOBAL_CACHE:
+#if 0 /* deprecated */
/* remember we want this enabled */
arg = va_arg(param, long);
data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
+#endif
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
@@ -142,6 +144,25 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
va_arg(param, char *));
break;
+ case CURLOPT_TLS13_CIPHERS:
+ if(Curl_ssl_tls13_ciphersuites()) {
+ /* set preferred list of TLS 1.3 cipher suites */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG],
+ va_arg(param, char *));
+ }
+ else
+ return CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_PROXY_TLS13_CIPHERS:
+ if(Curl_ssl_tls13_ciphersuites()) {
+ /* set preferred list of TLS 1.3 cipher suites for proxy */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
+ va_arg(param, char *));
+ }
+ else
+ return CURLE_NOT_BUILT_IN;
+ break;
+
case CURLOPT_RANDOM_FILE:
/*
* This is the path name to a file that contains random data to seed
@@ -822,6 +843,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
#else
if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
return CURLE_UNSUPPORTED_PROTOCOL;
+ if(arg == CURL_HTTP_VERSION_NONE)
+ arg = CURL_HTTP_VERSION_2TLS;
#endif
data->set.httpversion = arg;
break;
@@ -1584,14 +1607,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* String that holds the SSL crypto engine.
*/
argptr = va_arg(param, char *);
- if(argptr && argptr[0])
- result = Curl_ssl_set_engine(data, argptr);
+ if(argptr && argptr[0]) {
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr);
+ if(!result) {
+ result = Curl_ssl_set_engine(data, argptr);
+ }
+ }
break;
case CURLOPT_SSLENGINE_DEFAULT:
/*
* flag to set engine as default.
*/
+ Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL);
result = Curl_ssl_set_engine_default(data);
break;
case CURLOPT_CRLF:
@@ -1912,6 +1940,22 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
break;
+ case CURLOPT_UPLOAD_BUFFERSIZE:
+ /*
+ * The application kindly asks for a differently sized upload buffer.
+ * Cap it to sensible.
+ */
+ arg = va_arg(param, long);
+
+ if(arg > UPLOADBUFFER_MAX)
+ arg = UPLOADBUFFER_MAX;
+ else if(arg < UPLOADBUFFER_MIN)
+ arg = UPLOADBUFFER_MIN;
+
+ data->set.upload_buffer_size = arg;
+ Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */
+ break;
+
case CURLOPT_NOSIGNAL:
/*
* The application asks not to set any signal() or alarm() handlers,
@@ -1942,6 +1986,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
if(data->share->sslsession == data->state.session)
data->state.session = NULL;
+#ifdef USE_LIBPSL
+ if(data->psl == &data->share->psl)
+ data->psl = data->multi? &data->multi->psl: NULL;
+#endif
+
data->share->dirty--;
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -1973,8 +2022,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
data->state.session = data->share->sslsession;
}
- Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+#ifdef USE_LIBPSL
+ if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
+ data->psl = &data->share->psl;
+#endif
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
/* check for host cache not needed,
* it will be done by curl_easy_perform */
@@ -2562,6 +2615,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
break;
+ case CURLOPT_DISALLOW_USERNAME_IN_URL:
+ data->set.disallow_username_in_url =
+ (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_DOH_URL:
+ result = Curl_setstropt(&data->set.str[STRING_DOH],
+ va_arg(param, char *));
+ data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE;
+ break;
+ case CURLOPT_UPKEEP_INTERVAL_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.upkeep_interval_ms = arg;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index 55716c63b..f9287af23 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Florin Petriuc, <petriuc.florin@gmail.com>
+ * Copyright (C) 1998 - 2018, Florin Petriuc, <petriuc.florin@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -123,15 +123,11 @@ static const unsigned long K[64] = {
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-#ifndef MIN
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#endif
/* compress 512-bits */
static int sha256_compress(struct sha256_state *md,
unsigned char *buf)
{
- unsigned long S[8], W[64], t0, t1;
- unsigned long t;
+ unsigned long S[8], W[64];
int i;
/* copy state into S */
for(i = 0; i < 8; i++) {
@@ -146,12 +142,13 @@ static int sha256_compress(struct sha256_state *md,
W[i - 16];
}
/* Compress */
-#define RND(a,b,c,d,e,f,g,h,i) \
- t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
- t1 = Sigma0(a) + Maj(a, b, c); \
- d += t0; \
+#define RND(a,b,c,d,e,f,g,h,i) \
+ unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
h = t0 + t1;
for(i = 0; i < 64; ++i) {
+ unsigned long t;
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
@@ -200,7 +197,7 @@ static int SHA256_Update(struct sha256_state *md,
inlen -= block_size;
}
else {
- n = MIN(inlen, (block_size - md->curlen));
+ n = CURLMIN(inlen, (block_size - md->curlen));
memcpy(md->buf + md->curlen, in, n);
md->curlen += n;
in += n;
diff --git a/Utilities/cmcurl/lib/share.c b/Utilities/cmcurl/lib/share.c
index 870b191fc..3d5108610 100644
--- a/Utilities/cmcurl/lib/share.c
+++ b/Utilities/cmcurl/lib/share.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
@@ -25,6 +25,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "share.h"
+#include "psl.h"
#include "vtls/vtls.h"
#include "curl_memory.h"
@@ -106,6 +107,12 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
res = CURLSHE_NOMEM;
break;
+ case CURL_LOCK_DATA_PSL:
+#ifndef USE_LIBPSL
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
default:
res = CURLSHE_BAD_OPTION;
}
@@ -205,6 +212,8 @@ curl_share_cleanup(struct Curl_share *share)
}
#endif
+ Curl_psl_destroy(&share->psl);
+
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
free(share);
diff --git a/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h
index 4b13406d9..a7dea41ad 100644
--- a/Utilities/cmcurl/lib/share.h
+++ b/Utilities/cmcurl/lib/share.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
@@ -25,6 +25,7 @@
#include "curl_setup.h"
#include <curl/curl.h>
#include "cookie.h"
+#include "psl.h"
#include "urldata.h"
#include "conncache.h"
@@ -49,6 +50,9 @@ struct Curl_share {
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
#endif
+#ifdef USE_LIBPSL
+ struct PslCache psl;
+#endif
struct curl_ssl_session *sslsession;
size_t max_ssl_sessions;
diff --git a/Utilities/cmcurl/lib/slist.c b/Utilities/cmcurl/lib/slist.c
index e5adc0e71..392b84d13 100644
--- a/Utilities/cmcurl/lib/slist.c
+++ b/Utilities/cmcurl/lib/slist.c
@@ -142,4 +142,3 @@ void curl_slist_free_all(struct curl_slist *list)
item = next;
} while(next);
}
-
diff --git a/Utilities/cmcurl/lib/slist.h b/Utilities/cmcurl/lib/slist.h
index b3f498c35..d73dbf672 100644
--- a/Utilities/cmcurl/lib/slist.h
+++ b/Utilities/cmcurl/lib/slist.h
@@ -37,4 +37,3 @@ struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list,
char *data);
#endif /* HEADER_CURL_SLIST_H */
-
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 9ac61505c..e4f266e19 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -59,6 +59,7 @@
static CURLcode smb_setup_connection(struct connectdata *conn);
static CURLcode smb_connect(struct connectdata *conn, bool *done);
static CURLcode smb_connection_state(struct connectdata *conn, bool *done);
+static CURLcode smb_do(struct connectdata *conn, bool *done);
static CURLcode smb_request_state(struct connectdata *conn, bool *done);
static CURLcode smb_done(struct connectdata *conn, CURLcode status,
bool premature);
@@ -73,7 +74,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn);
const struct Curl_handler Curl_handler_smb = {
"SMB", /* scheme */
smb_setup_connection, /* setup_connection */
- ZERO_NULL, /* do_it */
+ smb_do, /* do_it */
smb_done, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
@@ -98,7 +99,7 @@ const struct Curl_handler Curl_handler_smb = {
const struct Curl_handler Curl_handler_smbs = {
"SMBS", /* scheme */
smb_setup_connection, /* setup_connection */
- ZERO_NULL, /* do_it */
+ smb_do, /* do_it */
smb_done, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
@@ -173,7 +174,6 @@ enum smb_req_state {
/* SMB request data */
struct smb_request {
enum smb_req_state state;
- char *share;
char *path;
unsigned short tid; /* Even if we connect to the same tree as another */
unsigned short fid; /* request, the tid will be different */
@@ -182,7 +182,7 @@ struct smb_request {
static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
{
- struct smb_conn *smb = &conn->proto.smbc;
+ struct smb_conn *smbc = &conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -194,12 +194,12 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
/* LAST */
};
- if(smb->state != newstate)
+ if(smbc->state != newstate)
infof(conn->data, "SMB conn %p state change from %s to %s\n",
- (void *)smb, names[smb->state], names[newstate]);
+ (void *)smbc, names[smbc->state], names[newstate]);
#endif
- smb->state = newstate;
+ smbc->state = newstate;
}
static void request_state(struct connectdata *conn,
@@ -228,6 +228,8 @@ static void request_state(struct connectdata *conn,
req->state = newstate;
}
+/* this should setup things in the connection, not in the easy
+ handle */
static CURLcode smb_setup_connection(struct connectdata *conn)
{
struct smb_request *req;
@@ -253,7 +255,6 @@ static CURLcode smb_connect(struct connectdata *conn, bool *done)
return CURLE_LOGIN_DENIED;
/* Initialize the connection state */
- memset(smbc, 0, sizeof(*smbc));
smbc->state = SMB_CONNECTING;
smbc->recv_buf = malloc(MAX_MESSAGE_SIZE);
if(!smbc->recv_buf)
@@ -366,7 +367,7 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
ssize_t bytes_written;
CURLcode result;
- result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer,
+ result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
len, &bytes_written);
if(result)
return result;
@@ -392,7 +393,7 @@ static CURLcode smb_flush(struct connectdata *conn)
return CURLE_OK;
result = Curl_write(conn, FIRSTSOCKET,
- conn->data->state.uploadbuffer + smbc->sent,
+ conn->data->state.ulbuf + smbc->sent,
len, &bytes_written);
if(result)
return result;
@@ -408,9 +409,12 @@ static CURLcode smb_flush(struct connectdata *conn)
static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
const void *msg, size_t msg_len)
{
- smb_format_message(conn, (struct smb_header *)conn->data->state.uploadbuffer,
+ CURLcode result = Curl_get_upload_buffer(conn->data);
+ if(result)
+ return result;
+ smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
cmd, msg_len);
- memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header),
+ memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len);
return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
@@ -475,11 +479,11 @@ static CURLcode smb_send_setup(struct connectdata *conn)
static CURLcode smb_send_tree_connect(struct connectdata *conn)
{
- struct smb_request *req = conn->data->req.protop;
struct smb_tree_connect msg;
+ struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes;
- size_t byte_count = strlen(conn->host.name) + strlen(req->share);
+ size_t byte_count = strlen(conn->host.name) + strlen(smbc->share);
byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
@@ -491,7 +495,7 @@ static CURLcode smb_send_tree_connect(struct connectdata *conn)
MSGCAT("\\\\");
MSGCAT(conn->host.name);
MSGCAT("\\");
- MSGCATNULL(req->share);
+ MSGCATNULL(smbc->share);
MSGCATNULL(SERVICENAME); /* Match any type of service */
byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count);
@@ -571,11 +575,15 @@ static CURLcode smb_send_read(struct connectdata *conn)
static CURLcode smb_send_write(struct connectdata *conn)
{
- struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer;
+ struct smb_write *msg;
struct smb_request *req = conn->data->req.protop;
curl_off_t offset = conn->data->req.offset;
-
curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
+ CURLcode result = Curl_get_upload_buffer(conn->data);
+ if(result)
+ return result;
+ msg = (struct smb_write *)conn->data->state.ulbuf;
+
if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
upload_size = MAX_PAYLOAD_SIZE - 1;
@@ -602,9 +610,10 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
/* Check if there is data in the transfer buffer */
if(!smbc->send_size && smbc->upload_size) {
- int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
- (int) smbc->upload_size;
- conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
+ size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ?
+ conn->data->set.upload_buffer_size :
+ smbc->upload_size;
+ conn->data->req.upload_fromhere = conn->data->state.ulbuf;
result = Curl_fillreadbuffer(conn, nread, &nread);
if(result && result != CURLE_AGAIN)
return result;
@@ -910,93 +919,84 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
static CURLcode smb_done(struct connectdata *conn, CURLcode status,
bool premature)
{
- struct smb_request *req = conn->data->req.protop;
-
(void) premature;
-
- Curl_safefree(req->share);
Curl_safefree(conn->data->req.protop);
-
return status;
}
static CURLcode smb_disconnect(struct connectdata *conn, bool dead)
{
struct smb_conn *smbc = &conn->proto.smbc;
- struct smb_request *req = conn->data->req.protop;
-
(void) dead;
-
+ Curl_safefree(smbc->share);
Curl_safefree(smbc->domain);
Curl_safefree(smbc->recv_buf);
-
- /* smb_done is not always called, so cleanup the request */
- if(req) {
- Curl_safefree(req->share);
- }
-
return CURLE_OK;
}
static int smb_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
- struct smb_conn *smbc = &conn->proto.smbc;
-
if(!numsocks)
return GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
+}
- if(smbc->send_size || smbc->upload_size)
- return GETSOCK_WRITESOCK(0);
+static CURLcode smb_do(struct connectdata *conn, bool *done)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_request *req = conn->data->req.protop;
- return GETSOCK_READSOCK(0);
+ *done = FALSE;
+ if(smbc->share) {
+ req->path = strchr(smbc->share, '\0');
+ if(req->path) {
+ req->path++;
+ return CURLE_OK;
+ }
+ }
+ return CURLE_URL_MALFORMAT;
}
static CURLcode smb_parse_url_path(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
- struct smb_request *req = data->req.protop;
+ struct smb_conn *smbc = &conn->proto.smbc;
char *path;
char *slash;
/* URL decode the path */
- result = Curl_urldecode(data, data->state.path, 0, &path, NULL, TRUE);
+ result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL, TRUE);
if(result)
return result;
/* Parse the path for the share */
- req->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
- if(!req->share) {
- free(path);
-
+ smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
+ free(path);
+ if(!smbc->share)
return CURLE_OUT_OF_MEMORY;
- }
- slash = strchr(req->share, '/');
+ slash = strchr(smbc->share, '/');
if(!slash)
- slash = strchr(req->share, '\\');
+ slash = strchr(smbc->share, '\\');
/* The share must be present */
if(!slash) {
- free(path);
-
+ Curl_safefree(smbc->share);
return CURLE_URL_MALFORMAT;
}
/* Parse the path for the file path converting any forward slashes into
backslashes */
*slash++ = 0;
- req->path = slash;
+
for(; *slash; slash++) {
if(*slash == '/')
*slash = '\\';
}
-
- free(path);
-
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/smb.h b/Utilities/cmcurl/lib/smb.h
index c3ee7ae03..9ce6b5615 100644
--- a/Utilities/cmcurl/lib/smb.h
+++ b/Utilities/cmcurl/lib/smb.h
@@ -35,6 +35,7 @@ struct smb_conn {
enum smb_conn_state state;
char *user;
char *domain;
+ char *share;
unsigned char challenge[8];
unsigned int session_key;
unsigned short uid;
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index 3f3b45a95..587562306 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -704,7 +704,6 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *line = data->state.buffer;
size_t len = strlen(line);
- size_t wordlen;
(void)instate; /* no use for this yet */
@@ -739,6 +738,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
/* Loop through the data line */
for(;;) {
size_t llen;
+ size_t wordlen;
unsigned int mechbit;
while(len &&
@@ -1441,7 +1441,6 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn,
static CURLcode smtp_setup_connection(struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
CURLcode result;
/* Clear the TLS upgraded flag */
@@ -1452,8 +1451,6 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
if(result)
return result;
- data->state.path++; /* don't include the initial slash */
-
return CURLE_OK;
}
@@ -1507,7 +1504,7 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
/* The SMTP struct is already initialised in smtp_connect() */
struct Curl_easy *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- const char *path = data->state.path;
+ const char *path = &data->state.up.path[1]; /* skip leading path */
char localhost[HOSTNAME_MAX + 1];
/* Calculate the path if necessary */
@@ -1563,13 +1560,14 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
if(!scratch || data->set.crlf) {
oldscratch = scratch;
- scratch = newscratch = malloc(2 * data->set.buffer_size);
+ scratch = newscratch = malloc(2 * data->set.upload_buffer_size);
if(!newscratch) {
failf(data, "Failed to alloc scratch buffer!");
return CURLE_OUT_OF_MEMORY;
}
}
+ DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread);
/* Have we already sent part of the EOB? */
eob_sent = smtp->eob;
diff --git a/Utilities/cmcurl/lib/sockaddr.h b/Utilities/cmcurl/lib/sockaddr.h
index 95ba4c3c9..db146803a 100644
--- a/Utilities/cmcurl/lib/sockaddr.h
+++ b/Utilities/cmcurl/lib/sockaddr.h
@@ -40,4 +40,3 @@ struct Curl_sockaddr_storage {
};
#endif /* HEADER_CURL_SOCKADDR_H */
-
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index ac4270eac..d2209ad89 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.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
@@ -57,10 +57,9 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
ssize_t nread;
ssize_t allread = 0;
int result;
- timediff_t timeleft;
*n = 0;
for(;;) {
- timeleft = Curl_timeleft(conn->data, NULL, TRUE);
+ timediff_t timeleft = Curl_timeleft(conn->data, NULL, TRUE);
if(timeleft < 0) {
/* we already got the timeout */
result = CURLE_OPERATION_TIMEDOUT;
@@ -99,7 +98,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
* destination server.
*
* Reference :
-* http://socks.permeo.com/protocol/socks4.protocol
+* https://www.openssh.com/txt/socks4.protocol
*
* Note :
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
@@ -116,7 +115,6 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
#define SOCKS4REQLEN 262
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
id */
- int result;
CURLcode code;
curl_socket_t sock = conn->sock[sockindex];
struct Curl_easy *data = conn->data;
@@ -220,11 +218,12 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
* Make connection
*/
{
+ int result;
ssize_t actualread;
ssize_t written;
ssize_t hostnamelen = 0;
- int packetsize = 9 +
- (int)strlen((char *)socksreq + 8); /* size including NUL */
+ ssize_t packetsize = 9 +
+ strlen((char *)socksreq + 8); /* size including NUL */
/* If SOCKS4a, set special invalid IP address 0.0.0.x */
if(protocol4a) {
@@ -617,11 +616,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(dns)
hp = dns->addr;
if(hp) {
- int i;
char buf[64];
Curl_printable_address(hp, buf, sizeof(buf));
if(hp->ai_family == AF_INET) {
+ int i;
struct sockaddr_in *saddr_in;
socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
@@ -634,6 +633,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
+ int i;
struct sockaddr_in6 *saddr_in6;
socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
@@ -789,4 +789,3 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
}
#endif /* CURL_DISABLE_PROXY */
-
diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h
index 348707e74..daa07c127 100644
--- a/Utilities/cmcurl/lib/socks.h
+++ b/Utilities/cmcurl/lib/socks.h
@@ -73,4 +73,3 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
#endif /* CURL_DISABLE_PROXY */
#endif /* HEADER_CURL_SOCKS_H */
-
diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c
index 69af446eb..baf07e00d 100644
--- a/Utilities/cmcurl/lib/splay.c
+++ b/Utilities/cmcurl/lib/splay.c
@@ -41,7 +41,6 @@ struct Curl_tree *Curl_splay(struct curltime i,
struct Curl_tree *t)
{
struct Curl_tree N, *l, *r, *y;
- long comp;
if(t == NULL)
return t;
@@ -49,7 +48,7 @@ struct Curl_tree *Curl_splay(struct curltime i,
l = r = &N;
for(;;) {
- comp = compare(i, t->key);
+ long comp = compare(i, t->key);
if(comp < 0) {
if(t->smaller == NULL)
break;
@@ -275,4 +274,3 @@ int Curl_splayremovebyaddr(struct Curl_tree *t,
return 0;
}
-
diff --git a/Utilities/cmcurl/lib/ssh-libssh.c b/Utilities/cmcurl/lib/ssh-libssh.c
index 34ef490c4..7d590891c 100644
--- a/Utilities/cmcurl/lib/ssh-libssh.c
+++ b/Utilities/cmcurl/lib/ssh-libssh.c
@@ -204,11 +204,21 @@ static CURLcode sftp_error_to_CURLE(int err)
return CURLE_SSH;
}
+#ifndef DEBUGBUILD
+#define state(x,y) mystate(x,y)
+#else
+#define state(x,y) mystate(x,y, __LINE__)
+#endif
+
/*
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct connectdata *conn, sshstate nowstate)
+static void mystate(struct connectdata *conn, sshstate nowstate
+#ifdef DEBUGBUILD
+ , int lineno
+#endif
+ )
{
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -278,8 +288,9 @@ static void state(struct connectdata *conn, sshstate nowstate)
if(sshc->state != nowstate) {
- infof(conn->data, "SSH %p state change from %s to %s\n",
- (void *) sshc, names[sshc->state], names[nowstate]);
+ infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
+ (void *) sshc, names[sshc->state], names[nowstate],
+ lineno);
}
#endif
@@ -418,7 +429,7 @@ cleanup:
}
#define MOVE_TO_ERROR_STATE(_r) { \
- state(conn, SSH_SESSION_FREE); \
+ state(conn, SSH_SESSION_DISCONNECT); \
sshc->actualcode = _r; \
rc = SSH_ERROR; \
break; \
@@ -486,7 +497,7 @@ restart:
if(rc < 0)
return SSH_ERROR;
- /* fallthrough */
+ /* FALLTHROUGH */
case 1:
sshc->kbd_state = 1;
@@ -561,7 +572,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
state(conn, SSH_S_STARTUP);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_S_STARTUP:
rc = ssh_connect(sshc->ssh_session);
@@ -575,7 +586,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_HOSTKEY);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_HOSTKEY:
rc = myssh_is_known(conn);
@@ -584,7 +595,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
state(conn, SSH_AUTHLIST);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_AUTHLIST:{
sshc->authed = FALSE;
@@ -607,6 +618,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
state(conn, SSH_AUTH_PKEY_INIT);
+ infof(data, "Authentication using SSH public key file\n");
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
state(conn, SSH_AUTH_GSSAPI);
@@ -651,6 +663,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc != SSH_OK) {
failf(data, "Could not load private key file %s",
data->set.str[STRING_SSH_PRIVATE_KEY]);
+ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
break;
}
@@ -659,8 +672,6 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
else {
- infof(data, "Authentication using SSH public key file\n");
-
rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
data->set.ssl.key_passwd);
if(rc == SSH_AUTH_AGAIN) {
@@ -748,7 +759,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
}
state(conn, SSH_AUTH_PASS);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_AUTH_PASS:
rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
@@ -812,7 +823,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
state(conn, SSH_SFTP_REALPATH);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SFTP_REALPATH:
/*
* Get the "home" directory
@@ -1279,7 +1290,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->readdir_attrs) {
sshc->readdir_filename = sshc->readdir_attrs->name;
sshc->readdir_longentry = sshc->readdir_attrs->longname;
- sshc->readdir_len = (int)strlen(sshc->readdir_filename);
+ sshc->readdir_len = strlen(sshc->readdir_filename);
if(data->set.ftp_list_only) {
char *tmpLine;
@@ -1306,11 +1317,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT,
(char *)sshc->readdir_filename,
- sshc->readdir_len, conn);
+ sshc->readdir_len);
}
}
else {
- sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+ sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
@@ -1371,12 +1382,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->readdir_filename == NULL)
sshc->readdir_len = 0;
else
- sshc->readdir_len = (int)strlen(sshc->readdir_tmp);
+ sshc->readdir_len = strlen(sshc->readdir_tmp);
sshc->readdir_longentry = NULL;
sshc->readdir_filename = sshc->readdir_tmp;
}
else {
- sshc->readdir_len = (int)strlen(sshc->readdir_link_attrs->name);
+ sshc->readdir_len = strlen(sshc->readdir_link_attrs->name);
sshc->readdir_filename = sshc->readdir_link_attrs->name;
sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
}
@@ -1408,7 +1419,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_longentry = NULL;
state(conn, SSH_SFTP_READDIR_BOTTOM);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
sshc->readdir_currLen += snprintf(sshc->readdir_line +
sshc->readdir_currLen,
@@ -1423,7 +1434,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* output debug output if that is requested */
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen, conn);
+ sshc->readdir_currLen);
}
data->req.bytecount += sshc->readdir_currLen;
}
@@ -1740,7 +1751,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
state(conn, SSH_SCP_DOWNLOAD);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SCP_DOWNLOAD:{
curl_off_t bytecount;
@@ -1805,7 +1816,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
state(conn, SSH_SESSION_DISCONNECT);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SESSION_DISCONNECT:
/* during weird times when we've been prematurely aborted, the channel
@@ -1822,7 +1833,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
conn->data->state.most_recent_ftp_entrypath = NULL;
state(conn, SSH_SESSION_FREE);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SESSION_FREE:
if(sshc->ssh_session) {
ssh_free(sshc->ssh_session);
@@ -2379,7 +2390,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!status && !premature && conn->data->set.postquote) {
+ if(!status && !premature && conn->data->set.postquote &&
+ !conn->bits.retry) {
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
state(conn, SSH_SFTP_CLOSE);
}
@@ -2437,7 +2449,7 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
return -1;
}
- /* fall-through */
+ /* FALLTHROUGH */
case 1:
conn->proto.sshc.sftp_recv_state = 1;
@@ -2500,8 +2512,8 @@ static void sftp_quote(struct connectdata *conn)
return;
}
if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4, conn);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
}
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index bf7bd54f9..da896196f 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -659,7 +659,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
libssh2_session_set_blocking(sshc->ssh_session, 0);
state(conn, SSH_S_STARTUP);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_S_STARTUP:
rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
@@ -675,7 +675,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_HOSTKEY);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_HOSTKEY:
/*
* Before we authenticate we should check the hostkey's fingerprint
@@ -1175,8 +1175,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
}
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
@@ -1933,17 +1933,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
case SSH_SFTP_READDIR:
- sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
- sshc->readdir_filename,
- PATH_MAX,
- sshc->readdir_longentry,
- PATH_MAX,
- &sshc->readdir_attrs);
- if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
+ rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
+ sshc->readdir_filename,
+ PATH_MAX,
+ sshc->readdir_longentry,
+ PATH_MAX,
+ &sshc->readdir_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(sshc->readdir_len > 0) {
+ if(rc > 0) {
+ sshc->readdir_len = (size_t) rc;
sshc->readdir_filename[sshc->readdir_len] = '\0';
if(data->set.ftp_list_only) {
@@ -1970,11 +1970,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* output debug output if that is requested */
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
- sshc->readdir_len, conn);
+ sshc->readdir_len);
}
}
else {
- sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+ sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
@@ -2008,13 +2008,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
- else if(sshc->readdir_len == 0) {
+ else if(rc == 0) {
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
state(conn, SSH_SFTP_READDIR_DONE);
break;
}
- else if(sshc->readdir_len <= 0) {
+ else if(rc < 0) {
err = sftp_libssh2_last_error(sshc->sftp_session);
result = sftp_libssh2_error_to_CURLE(err);
sshc->actualcode = result?result:CURLE_SSH;
@@ -2029,16 +2029,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
case SSH_SFTP_READDIR_LINK:
- sshc->readdir_len =
+ rc =
libssh2_sftp_symlink_ex(sshc->sftp_session,
sshc->readdir_linkPath,
curlx_uztoui(strlen(sshc->readdir_linkPath)),
sshc->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK);
- if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
+ sshc->readdir_len = (size_t) rc;
Curl_safefree(sshc->readdir_linkPath);
/* get room for the filename and extra output */
@@ -2079,7 +2079,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* output debug output if that is requested */
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen, conn);
+ sshc->readdir_currLen);
}
data->req.bytecount += sshc->readdir_currLen;
}
@@ -2926,7 +2926,7 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
int rc;
ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
if(!ssh->kh) {
- /* eeek. TODO: free the ssh_session! */
+ libssh2_session_free(ssh->ssh_session);
return CURLE_FAILED_INIT;
}
@@ -3219,7 +3219,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!status && !premature && conn->data->set.postquote) {
+ if(!status && !premature && conn->data->set.postquote &&
+ !conn->bits.retry) {
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
state(conn, SSH_SFTP_CLOSE);
}
diff --git a/Utilities/cmcurl/lib/ssh.h b/Utilities/cmcurl/lib/ssh.h
index 1c1355077..0620aac32 100644
--- a/Utilities/cmcurl/lib/ssh.h
+++ b/Utilities/cmcurl/lib/ssh.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, 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
@@ -131,7 +131,7 @@ struct ssh_conn {
quote command fails) */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
- int readdir_len, readdir_totalLen, readdir_currLen;
+ size_t readdir_len, readdir_totalLen, readdir_currLen;
char *readdir_line;
char *readdir_linkPath;
/* end of READDIR stuff */
diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h
index ea2abc8b6..6fee3840e 100644
--- a/Utilities/cmcurl/lib/strcase.h
+++ b/Utilities/cmcurl/lib/strcase.h
@@ -46,6 +46,5 @@ char Curl_raw_toupper(char in);
#define checkprefix(a,b) curl_strnequal(a,b,strlen(a))
void Curl_strntoupper(char *dest, const char *src, size_t n);
-char Curl_raw_toupper(char in);
#endif /* HEADER_CURL_STRCASE_H */
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 19cb04416..51e7978b7 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -81,7 +81,7 @@ void *Curl_memdup(const void *src, size_t length)
* Curl_saferealloc(ptr, size)
*
* Does a normal realloc(), but will free the data pointer if the realloc
- * fails. If 'size' is zero, it will free the data and return a failure.
+ * fails. If 'size' is non-zero, it will free the data and return a failure.
*
* This convenience function is provided and used to help us avoid a common
* mistake pattern when we could pass in a zero, catch the NULL return and end
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 0295d6c27..47ef44a66 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -191,9 +191,6 @@ curl_easy_strerror(CURLcode error)
case CURLE_TELNET_OPTION_SYNTAX :
return "Malformed telnet option";
- case CURLE_PEER_FAILED_VERIFICATION:
- return "SSL peer certificate or SSH remote key was not OK";
-
case CURLE_GOT_NOTHING:
return "Server returned nothing (no headers, no data)";
@@ -218,9 +215,8 @@ curl_easy_strerror(CURLcode error)
case CURLE_SSL_CIPHER:
return "Couldn't use specified SSL cipher";
- case CURLE_SSL_CACERT:
- return "Peer certificate cannot be authenticated with given CA "
- "certificates";
+ case CURLE_PEER_FAILED_VERIFICATION:
+ return "SSL peer certificate or SSH remote key was not OK";
case CURLE_SSL_CACERT_BADFILE:
return "Problem with the SSL CA cert (path? access rights?)";
@@ -324,6 +320,7 @@ curl_easy_strerror(CURLcode error)
case CURLE_OBSOLETE44:
case CURLE_OBSOLETE46:
case CURLE_OBSOLETE50:
+ case CURLE_OBSOLETE51:
case CURLE_OBSOLETE57:
case CURL_LAST:
break;
diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c
index cfbbf3279..6b8004e5b 100644
--- a/Utilities/cmcurl/lib/system_win32.c
+++ b/Utilities/cmcurl/lib/system_win32.c
@@ -26,6 +26,7 @@
#include <curl/curl.h>
#include "system_win32.h"
+#include "warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -134,8 +135,9 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
break;
case VERSION_LESS_THAN_EQUAL:
- if(osver.dwMajorVersion <= majorVersion &&
- osver.dwMinorVersion <= minorVersion)
+ if(osver.dwMajorVersion < majorVersion ||
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion <= minorVersion))
matched = TRUE;
break;
@@ -146,8 +148,9 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
break;
case VERSION_GREATER_THAN_EQUAL:
- if(osver.dwMajorVersion >= majorVersion &&
- osver.dwMinorVersion >= minorVersion)
+ if(osver.dwMajorVersion > majorVersion ||
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion >= minorVersion))
matched = TRUE;
break;
@@ -278,7 +281,9 @@ HMODULE Curl_load_library(LPCTSTR filename)
/* Attempt to find LoadLibraryEx() which is only available on Windows 2000
and above */
- pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
+ pLoadLibraryEx =
+ CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN,
+ (GetProcAddress(hKernel32, LOADLIBARYEX)));
/* Detect if there's already a path in the filename and load the library if
there is. Note: Both back slashes and forward slashes have been supported
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index d71c8e067..05fe744db 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.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
@@ -52,10 +52,6 @@
#include "connect.h"
#include "progress.h"
#include "system_win32.h"
-
-#define TELOPTS
-#define TELCMDS
-
#include "arpa_telnet.h"
#include "select.h"
#include "strcase.h"
@@ -74,10 +70,10 @@
x->subend = x->subpointer; \
CURL_SB_CLEAR(x); \
} WHILE_FALSE
-#define CURL_SB_ACCUM(x,c) \
- do { \
- if(x->subpointer < (x->subbuffer + sizeof x->subbuffer)) \
- *x->subpointer++ = (c); \
+#define CURL_SB_ACCUM(x,c) \
+ do { \
+ if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer))) \
+ *x->subpointer++ = (c); \
} WHILE_FALSE
#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
@@ -92,6 +88,7 @@
#endif
#ifdef USE_WINSOCK
+typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void);
typedef FARPROC WSOCK2_FUNC;
static CURLcode check_wsock2(struct Curl_easy *data);
#endif
@@ -109,8 +106,10 @@ static void printoption(struct Curl_easy *data,
static void negotiate(struct connectdata *);
static void send_negotiation(struct connectdata *, int cmd, int option);
-static void set_local_option(struct connectdata *, int cmd, int option);
-static void set_remote_option(struct connectdata *, int cmd, int option);
+static void set_local_option(struct connectdata *conn,
+ int option, int newstate);
+static void set_remote_option(struct connectdata *conn,
+ int option, int newstate);
static void printsub(struct Curl_easy *data,
int direction, unsigned char *pointer,
@@ -311,9 +310,6 @@ static void negotiate(struct connectdata *conn)
static void printoption(struct Curl_easy *data,
const char *direction, int cmd, int option)
{
- const char *fmt;
- const char *opt;
-
if(data->set.verbose) {
if(cmd == CURL_IAC) {
if(CURL_TELCMD_OK(option))
@@ -322,9 +318,12 @@ static void printoption(struct Curl_easy *data,
infof(data, "%s IAC %d\n", direction, option);
}
else {
- fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
- (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
+ const char *fmt = (cmd == CURL_WILL) ? "WILL" :
+ (cmd == CURL_WONT) ? "WONT" :
+ (cmd == CURL_DO) ? "DO" :
+ (cmd == CURL_DONT) ? "DONT" : 0;
if(fmt) {
+ const char *opt;
if(CURL_TELOPT_OK(option))
opt = CURL_TELOPT(option);
else if(option == CURL_TELOPT_EXOPL)
@@ -348,7 +347,6 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
{
unsigned char buf[3];
ssize_t bytes_written;
- int err;
struct Curl_easy *data = conn->data;
buf[0] = CURL_IAC;
@@ -357,7 +355,7 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
if(bytes_written < 0) {
- err = SOCKERRNO;
+ int err = SOCKERRNO;
failf(data,"Sending data failed (%d)",err);
}
@@ -710,9 +708,8 @@ static void printsub(struct Curl_easy *data,
unsigned char *pointer, /* where suboption data is */
size_t length) /* length of suboption data */
{
- unsigned int i = 0;
-
if(data->set.verbose) {
+ unsigned int i = 0;
if(direction) {
infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
if(length >= 3) {
@@ -764,7 +761,7 @@ static void printsub(struct Curl_easy *data,
switch(pointer[0]) {
case CURL_TELOPT_NAWS:
if(length > 4)
- infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2],
+ infof(data, "Width: %d ; Height: %d", (pointer[1]<<8) | pointer[2],
(pointer[3]<<8) | pointer[4]);
break;
default:
@@ -928,7 +925,6 @@ static void suboption(struct connectdata *conn)
unsigned char temp[2048];
ssize_t bytes_written;
size_t len;
- size_t tmplen;
int err;
char varname[128] = "";
char varval[128] = "";
@@ -968,7 +964,7 @@ static void suboption(struct connectdata *conn)
len = 4;
for(v = tn->telnet_vars; v; v = v->next) {
- tmplen = (strlen(v->data) + 1);
+ size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
@@ -1017,7 +1013,7 @@ static void sendsuboption(struct connectdata *conn, int option)
CURL_SB_ACCUM(tn, CURL_IAC);
CURL_SB_ACCUM(tn, CURL_SB);
CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
- /* We must deal either with litte or big endian processors */
+ /* We must deal either with little or big endian processors */
/* Window size must be sent according to the 'network order' */
x = htons(tn->subopt_wsx);
y = htons(tn->subopt_wsy);
@@ -1223,7 +1219,7 @@ CURLcode telrcv(struct connectdata *conn,
static CURLcode send_telnet_data(struct connectdata *conn,
char *buffer, ssize_t nread)
{
- ssize_t escapes, i, j, outlen;
+ ssize_t escapes, i, outlen;
unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK;
ssize_t bytes_written, total_written;
@@ -1238,6 +1234,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
if(outlen == nread)
outbuf = (unsigned char *)buffer;
else {
+ ssize_t j;
outbuf = malloc(nread + escapes + 1);
if(!outbuf)
return CURLE_OUT_OF_MEMORY;
@@ -1306,7 +1303,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
#ifdef USE_WINSOCK
HMODULE wsock2;
WSOCK2_FUNC close_event_func;
- WSOCK2_FUNC create_event_func;
+ WSOCK2_EVENT create_event_func;
WSOCK2_FUNC event_select_func;
WSOCK2_FUNC enum_netevents_func;
WSAEVENT event_handle;
@@ -1315,7 +1312,6 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
HANDLE objs[2];
DWORD obj_count;
DWORD wait_timeout;
- DWORD waitret;
DWORD readfile_read;
int err;
#else
@@ -1361,7 +1357,9 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
/* Grab a pointer to WSACreateEvent */
- create_event_func = GetProcAddress(wsock2, "WSACreateEvent");
+ create_event_func =
+ CURLX_FUNCTION_CAST(WSOCK2_EVENT,
+ (GetProcAddress(wsock2, "WSACreateEvent")));
if(create_event_func == NULL) {
failf(data, "failed to find WSACreateEvent function (%u)", GetLastError());
FreeLibrary(wsock2);
@@ -1438,7 +1436,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
/* Keep on listening and act on events */
while(keepon) {
const DWORD buf_size = (DWORD)data->set.buffer_size;
- waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
+ DWORD waitret = WaitForMultipleObjects(obj_count, objs,
+ FALSE, wait_timeout);
switch(waitret) {
case WAIT_TIMEOUT:
{
@@ -1607,7 +1606,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
case 0: /* timeout */
pfd[0].revents = 0;
pfd[1].revents = 0;
- /* fall through */
+ /* FALLTHROUGH */
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
diff --git a/Utilities/cmcurl/lib/telnet.h b/Utilities/cmcurl/lib/telnet.h
index 419a399b7..668a78a13 100644
--- a/Utilities/cmcurl/lib/telnet.h
+++ b/Utilities/cmcurl/lib/telnet.h
@@ -26,4 +26,3 @@ extern const struct Curl_handler Curl_handler_telnet;
#endif
#endif /* HEADER_CURL_TELNET_H */
-
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index b32960f82..5b74e8e08 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -451,7 +451,6 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
ssize_t senddata;
const char *mode = "octet";
char *filename;
- char buf[64];
struct Curl_easy *data = state->conn->data;
CURLcode result = CURLE_OK;
@@ -486,7 +485,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
- result = Curl_urldecode(data, &state->conn->data->state.path[1], 0,
+ result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
&filename, NULL, FALSE);
if(result)
return result;
@@ -504,6 +503,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* optional addition of TFTP options */
if(!data->set.tftp_no_options) {
+ char buf[64];
/* add tsize option */
if(data->set.upload && (data->state.infilesize != -1))
snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
@@ -710,10 +710,9 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
{
struct Curl_easy *data = state->conn->data;
ssize_t sbytes;
- int rblock;
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
- int cb; /* Bytes currently read */
+ size_t cb; /* Bytes currently read */
switch(event) {
@@ -721,7 +720,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
case TFTP_EVENT_OACK:
if(event == TFTP_EVENT_ACK) {
/* Ack the packet */
- rblock = getrpacketblock(&state->rpacket);
+ int rblock = getrpacketblock(&state->rpacket);
if(rblock != state->block &&
/* There's a bug in tftpd-hpa that causes it to send us an ack for
@@ -766,7 +765,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
state->retries = 0;
setpacketevent(&state->spacket, TFTP_EVENT_DATA);
setpacketblock(&state->spacket, state->block);
- if(state->block > 1 && state->sbytes < (int)state->blksize) {
+ if(state->block > 1 && state->sbytes < state->blksize) {
state->state = TFTP_STATE_FIN;
return CURLE_OK;
}
@@ -782,7 +781,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
&cb);
if(result)
return result;
- state->sbytes += cb;
+ state->sbytes += (int)cb;
state->conn->data->req.upload_fromhere += cb;
} while(state->sbytes < state->blksize && cb != 0);
@@ -969,7 +968,7 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
static CURLcode tftp_connect(struct connectdata *conn, bool *done)
{
tftp_state_data_t *state;
- int blksize, rc;
+ int blksize;
blksize = TFTP_BLKSIZE_DEFAULT;
@@ -1028,8 +1027,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* assume uses the same IP version and thus hopefully this works for both
* IPv4 and IPv6...
*/
- rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
- conn->ip_addr->ai_addrlen);
+ int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
+ conn->ip_addr->ai_addrlen);
if(rc) {
failf(conn->data, "bind() failed; %s",
Curl_strerror(conn, SOCKERRNO));
@@ -1148,8 +1147,11 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
case TFTP_EVENT_ERROR:
{
unsigned short error = getrpacketblock(&state->rpacket);
+ char *str = (char *)state->rpacket.data + 4;
+ size_t strn = state->rbytes - 4;
state->error = (tftp_error_t)error;
- infof(data, "%s\n", (const char *)state->rpacket.data + 4);
+ if(Curl_strnlen(str, strn) < strn)
+ infof(data, "TFTP error: %s\n", str);
break;
}
case TFTP_EVENT_ACK:
@@ -1221,7 +1223,6 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
**********************************************************/
static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
{
- int rc;
tftp_event_t event;
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
@@ -1245,7 +1246,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
}
else {
/* no timeouts to handle, check our socket */
- rc = SOCKET_READABLE(state->sockfd, 0);
+ int rc = SOCKET_READABLE(state->sockfd, 0);
if(rc == -1) {
/* bail out */
@@ -1368,18 +1369,18 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
{
struct Curl_easy *data = conn->data;
char *type;
- char command;
conn->socktype = SOCK_DGRAM; /* UDP datagram based */
/* TFTP URLs support an extension like ";mode=<typecode>" that
* we'll try to get now! */
- type = strstr(data->state.path, ";mode=");
+ type = strstr(data->state.up.path, ";mode=");
if(!type)
type = strstr(conn->host.rawalloc, ";mode=");
if(type) {
+ char command;
*type = 0; /* it was in the middle of the hostname */
command = Curl_raw_toupper(type[6]);
diff --git a/Utilities/cmcurl/lib/tftp.h b/Utilities/cmcurl/lib/tftp.h
index c2325b232..1335f64bd 100644
--- a/Utilities/cmcurl/lib/tftp.h
+++ b/Utilities/cmcurl/lib/tftp.h
@@ -26,4 +26,3 @@ extern const struct Curl_handler Curl_handler_tftp;
#endif
#endif /* HEADER_CURL_TFTP_H */
-
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index f4bf83531..dce1a761e 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.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
@@ -33,7 +33,8 @@ struct curltime Curl_now(void)
*/
struct curltime now;
#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
- (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
+ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
DWORD milliseconds = GetTickCount();
now.tv_sec = milliseconds / 1000;
now.tv_usec = (milliseconds % 1000) * 1000;
@@ -60,7 +61,23 @@ struct curltime Curl_now(void)
struct timeval now;
struct curltime cnow;
struct timespec tsnow;
- if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+
+ /*
+ ** clock_gettime() may be defined by Apple's SDK as weak symbol thus
+ ** code compiles but fails during run-time if clock_gettime() is
+ ** called on unsupported OS version.
+ */
+#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
+ bool have_clock_gettime = FALSE;
+ if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
+ have_clock_gettime = TRUE;
+#endif
+
+ if(
+#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
+ have_clock_gettime &&
+#endif
+ (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) {
cnow.tv_sec = tsnow.tv_sec;
cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
}
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 131f2dc7c..05ba862c2 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -75,6 +75,7 @@
#include "http2.h"
#include "mime.h"
#include "strcase.h"
+#include "urlapi-int.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -106,15 +107,26 @@ char *Curl_checkheaders(const struct connectdata *conn,
}
#endif
+CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
+{
+ if(!data->state.ulbuf) {
+ data->state.ulbuf = malloc(data->set.upload_buffer_size);
+ if(!data->state.ulbuf)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
/*
* This function will call the read callback to fill our buffer with data
* to upload.
*/
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+ size_t *nreadp)
{
struct Curl_easy *data = conn->data;
- size_t buffersize = (size_t)bytes;
- int nread;
+ size_t buffersize = bytes;
+ size_t nread;
#ifdef CURL_DOES_CONVERSIONS
bool sending_http_headers = FALSE;
@@ -134,11 +146,9 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
}
- /* 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);
+ nread = data->state.fread_func(data->req.upload_fromhere, 1,
+ buffersize, data->state.in);
Curl_set_in_callback(data, false);
if(nread == CURL_READFUNC_ABORT) {
@@ -167,7 +177,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
return CURLE_OK; /* nothing was read */
}
- else if((size_t)nread > buffersize) {
+ else if(nread > buffersize) {
/* the read function returned a too large value */
*nreadp = 0;
failf(data, "read function returned funny value");
@@ -226,13 +236,13 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
#ifdef CURL_DOES_CONVERSIONS
{
CURLcode result;
- int length;
+ size_t length;
if(data->set.prefer_ascii)
/* translate the protocol and data */
length = nread;
else
/* just translate the protocol portion */
- length = (int)strlen(hexbuffer);
+ length = strlen(hexbuffer);
result = Curl_convert_to_network(data, data->req.upload_fromhere,
length);
/* Curl_convert_to_network calls failf if unsuccessful */
@@ -247,7 +257,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
infof(data, "Signaling end of chunked upload via terminating chunk.\n");
}
- nread += (int)strlen(endofline_native); /* for the added end of line */
+ nread += strlen(endofline_native); /* for the added end of line */
}
#ifdef CURL_DOES_CONVERSIONS
else if((data->set.prefer_ascii) && (!sending_http_headers)) {
@@ -353,7 +363,7 @@ static int data_pending(const struct connectdata *conn)
return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
#if defined(USE_NGHTTP2)
Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
- /* For HTTP/2, we may read up everything including responde body
+ /* For HTTP/2, we may read up everything including response body
with header fields in Curl_http_readwrite_headers. If no
content-length is provided, curl waits for the connection
close, which we emulate it using conn->proto.httpc.closed =
@@ -444,7 +454,6 @@ static CURLcode readwrite_data(struct Curl_easy *data,
CURLcode result = CURLE_OK;
ssize_t nread; /* number of bytes read */
size_t excess = 0; /* excess bytes read */
- bool is_empty_data = FALSE;
bool readmore = FALSE; /* used by RTP to signal for more data */
int maxloops = 100;
@@ -454,6 +463,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
do {
+ bool is_empty_data = FALSE;
size_t buffersize = data->set.buffer_size;
size_t bytestoread = buffersize;
@@ -557,7 +567,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
infof(data,
"Rewinding stream by : %zd"
" bytes on url %s (zero-length body)\n",
- nread, data->state.path);
+ nread, data->state.up.path);
read_rewind(conn, (size_t)nread);
}
else {
@@ -565,7 +575,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
"Excess found in a non pipelined read:"
" excess = %zd"
" url = %s (zero-length body)\n",
- nread, data->state.path);
+ nread, data->state.up.path);
}
}
@@ -660,14 +670,14 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(data->set.verbose) {
if(k->badheader) {
Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
- (size_t)k->hbuflen, conn);
+ (size_t)k->hbuflen);
if(k->badheader == HEADER_PARTHEADER)
Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread, conn);
+ k->str, (size_t)nread);
}
else
Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread, conn);
+ k->str, (size_t)nread);
}
#ifndef CURL_DISABLE_HTTP
@@ -734,7 +744,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
" bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
", maxdownload = %" CURL_FORMAT_CURL_OFF_T
", bytecount = %" CURL_FORMAT_CURL_OFF_T ", nread = %zd)\n",
- excess, data->state.path,
+ excess, data->state.up.path,
k->size, k->maxdownload, k->bytecount, nread);
read_rewind(conn, excess);
}
@@ -797,7 +807,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
nread);
}
}
- else
+ else if(!k->ignorebody)
result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -869,6 +879,26 @@ static CURLcode done_sending(struct connectdata *conn,
return CURLE_OK;
}
+#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
+#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
+#endif
+
+static void win_update_buffer_size(curl_socket_t sockfd)
+{
+ int result;
+ ULONG ideal;
+ DWORD ideallen;
+ result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
+ &ideal, sizeof(ideal), &ideallen, 0, 0);
+ if(result == 0) {
+ setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
+ (const char *)&ideal, sizeof(ideal));
+ }
+}
+#else
+#define win_update_buffer_size(x)
+#endif
/*
* Send data to upload to the server, when the socket is writable.
@@ -894,13 +924,16 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* only read more data if there's no upload data already
present in the upload buffer */
if(0 == k->upload_present) {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
/* init the "upload from here" pointer */
- k->upload_fromhere = data->state.uploadbuffer;
+ k->upload_fromhere = data->state.ulbuf;
if(!k->upload_done) {
/* HTTP pollution, this should be written nicer to become more
protocol agnostic. */
- int fillcount;
+ size_t fillcount;
struct HTTP *http = k->protop;
if((k->exp100 == EXP100_SENDING_REQUEST) &&
@@ -927,11 +960,12 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
sending_http_headers = FALSE;
}
- result = Curl_fillreadbuffer(conn, UPLOAD_BUFSIZE, &fillcount);
+ result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size,
+ &fillcount);
if(result)
return result;
- nread = (ssize_t)fillcount;
+ nread = fillcount;
}
else
nread = 0; /* we're done uploading/reading */
@@ -959,7 +993,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
(data->set.crlf))) {
/* Do we need to allocate a scratch buffer? */
if(!data->state.scratch) {
- data->state.scratch = malloc(2 * data->set.buffer_size);
+ data->state.scratch = malloc(2 * data->set.upload_buffer_size);
if(!data->state.scratch) {
failf(data, "Failed to alloc scratch buffer!");
@@ -1020,14 +1054,15 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
k->upload_fromhere, /* buffer pointer */
k->upload_present, /* buffer size */
&bytes_written); /* actually sent */
-
if(result)
return result;
+ win_update_buffer_size(conn->writesockfd);
+
if(data->set.verbose)
/* show the data before we change the pointer upload_fromhere */
Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
- (size_t)bytes_written, conn);
+ (size_t)bytes_written);
k->writebytecount += bytes_written;
@@ -1050,7 +1085,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
}
else {
/* we've uploaded that buffer now */
- k->upload_fromhere = data->state.uploadbuffer;
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+ k->upload_fromhere = data->state.ulbuf;
k->upload_present = 0; /* no more bytes left */
if(k->upload_done) {
@@ -1417,314 +1455,11 @@ CURLcode Curl_posttransfer(struct Curl_easy *data)
return CURLE_OK;
}
-#ifndef CURL_DISABLE_HTTP
-/*
- * Find the separator at the end of the host name, or the '?' in cases like
- * http://www.url.com?id=2380
- */
-static const char *find_host_sep(const char *url)
-{
- const char *sep;
- const char *query;
-
- /* Find the start of the hostname */
- sep = strstr(url, "//");
- if(!sep)
- sep = url;
- else
- sep += 2;
-
- query = strchr(sep, '?');
- sep = strchr(sep, '/');
-
- if(!sep)
- sep = url + strlen(url);
-
- if(!query)
- query = url + strlen(url);
-
- return sep < query ? sep : query;
-}
-
-/*
- * 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
- * will fail.
- */
-static size_t strlen_url(const char *url, bool relative)
-{
- const unsigned char *ptr;
- size_t newlen = 0;
- bool left = TRUE; /* left side of the ? */
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(ptr = (unsigned char *)url; *ptr; ptr++) {
-
- if(ptr < host_sep) {
- ++newlen;
- continue;
- }
-
- switch(*ptr) {
- case '?':
- left = FALSE;
- /* fall through */
- default:
- if(urlchar_needs_escaping(*ptr))
- newlen += 2;
- newlen++;
- break;
- case ' ':
- if(left)
- newlen += 3;
- else
- newlen++;
- break;
- }
- }
- return newlen;
-}
-
-/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
- * the source URL accordingly.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
- */
-static void strcpy_url(char *output, const char *url, bool relative)
-{
- /* we must add this with whitespace-replacing */
- bool left = TRUE;
- const unsigned char *iptr;
- char *optr = output;
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(iptr = (unsigned char *)url; /* read from here */
- *iptr; /* until zero byte */
- iptr++) {
-
- if(iptr < host_sep) {
- *optr++ = *iptr;
- continue;
- }
-
- switch(*iptr) {
- case '?':
- left = FALSE;
- /* fall through */
- default:
- if(urlchar_needs_escaping(*iptr)) {
- snprintf(optr, 4, "%%%02x", *iptr);
- optr += 3;
- }
- else
- *optr++=*iptr;
- break;
- case ' ':
- if(left) {
- *optr++='%'; /* add a '%' */
- *optr++='2'; /* add a '2' */
- *optr++='0'; /* add a '0' */
- }
- else
- *optr++='+'; /* add a '+' here */
- break;
- }
- }
- *optr = 0; /* zero terminate output buffer */
-
-}
-
-/*
- * Returns true if the given URL is absolute (as opposed to relative)
- */
-static bool is_absolute_url(const char *url)
-{
- char prot[16]; /* URL protocol string storage */
- char letter; /* used for a silly sscanf */
-
- return (2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)) ? TRUE : FALSE;
-}
-
-/*
- * Concatenate a relative URL to a base URL making it absolute.
- * URL-encodes any spaces.
- * The returned pointer must be freed by the caller unless NULL
- * (returns NULL on out of memory).
- */
-static char *concat_url(const char *base, const char *relurl)
-{
- /***
- TRY to append this new path to the old URL
- to the right of the host part. Oh crap, this is doomed to cause
- problems in the future...
- */
- char *newest;
- char *protsep;
- char *pathsep;
- size_t newlen;
- bool host_changed = FALSE;
-
- const char *useurl = relurl;
- size_t urllen;
-
- /* we must make our own copy of the URL to play with, as it may
- point to read-only data */
- char *url_clone = strdup(base);
-
- if(!url_clone)
- return NULL; /* skip out of this NOW */
-
- /* protsep points to the start of the host name */
- protsep = strstr(url_clone, "//");
- if(!protsep)
- protsep = url_clone;
- else
- protsep += 2; /* pass the slashes */
-
- if('/' != relurl[0]) {
- int level = 0;
-
- /* First we need to find out if there's a ?-letter in the URL,
- and cut it and the right-side of that off */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
-
- /* we have a relative path to append to the last slash if there's one
- available, or if the new URL is just a query string (starts with a
- '?') we append the new one at the end of the entire currently worked
- out URL */
- if(useurl[0] != '?') {
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- }
-
- /* Check if there's any slash after the host name, and if so, remember
- that position instead */
- pathsep = strchr(protsep, '/');
- if(pathsep)
- protsep = pathsep + 1;
- else
- protsep = NULL;
-
- /* now deal with one "./" or any amount of "../" in the newurl
- and act accordingly */
-
- if((useurl[0] == '.') && (useurl[1] == '/'))
- useurl += 2; /* just skip the "./" */
-
- while((useurl[0] == '.') &&
- (useurl[1] == '.') &&
- (useurl[2] == '/')) {
- level++;
- useurl += 3; /* pass the "../" */
- }
-
- if(protsep) {
- while(level--) {
- /* cut off one more level from the right of the original URL */
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- else {
- *protsep = 0;
- break;
- }
- }
- }
- }
- else {
- /* We got a new absolute path for this server */
-
- if((relurl[0] == '/') && (relurl[1] == '/')) {
- /* the new URL starts with //, just keep the protocol part from the
- original one */
- *protsep = 0;
- useurl = &relurl[2]; /* we keep the slashes from the original, so we
- skip the new ones */
- host_changed = TRUE;
- }
- else {
- /* cut off the original URL from the first slash, or deal with URLs
- without slash */
- pathsep = strchr(protsep, '/');
- if(pathsep) {
- /* When people use badly formatted URLs, such as
- "http://www.url.com?dir=/home/daniel" we must not use the first
- slash, if there's a ?-letter before it! */
- char *sep = strchr(protsep, '?');
- if(sep && (sep < pathsep))
- pathsep = sep;
- *pathsep = 0;
- }
- else {
- /* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.url.com?id=2380" which doesn't
- use a slash separator as it is supposed to, we need to check for a
- ?-letter as well! */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
- }
- }
- }
-
- /* If the new part contains a space, this is a mighty stupid redirect
- but we still make an effort to do "right". To the left of a '?'
- letter we replace each space with %20 while it is replaced with '+'
- on the right side of the '?' letter.
- */
- newlen = strlen_url(useurl, !host_changed);
-
- urllen = strlen(url_clone);
-
- newest = malloc(urllen + 1 + /* possible slash */
- newlen + 1 /* zero byte */);
-
- if(!newest) {
- free(url_clone); /* don't leak this */
- return NULL;
- }
-
- /* copy over the root url part */
- memcpy(newest, url_clone, urllen);
-
- /* check if we need to append a slash */
- if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
- ;
- else
- newest[urllen++]='/';
-
- /* then append the new piece on the right side */
- strcpy_url(&newest[urllen], useurl, !host_changed);
-
- free(url_clone);
-
- return newest;
-}
-#endif /* CURL_DISABLE_HTTP */
-
/*
* Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
* as given by the remote server and set up the new URL to request.
+ *
+ * This function DOES NOT FREE the given url.
*/
CURLcode Curl_follow(struct Curl_easy *data,
char *newurl, /* the Location: string */
@@ -1741,6 +1476,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* Location: redirect */
bool disallowport = FALSE;
bool reachedmax = FALSE;
+ CURLUcode uc;
if(type == FOLLOW_REDIR) {
if((data->set.maxredirs != -1) &&
@@ -1773,33 +1509,19 @@ CURLcode Curl_follow(struct Curl_easy *data,
}
}
- if(!is_absolute_url(newurl)) {
- /***
- *DANG* this is an RFC 2068 violation. The URL is supposed
- to be absolute and this doesn't seem to be that!
- */
- char *absolute = concat_url(data->change.url, newurl);
- if(!absolute)
- return CURLE_OUT_OF_MEMORY;
- newurl = absolute;
- }
- else {
- /* The new URL MAY contain space or high byte values, that means a mighty
- stupid redirect URL but we still make an effort to do "right". */
- char *newest;
- size_t newlen = strlen_url(newurl, FALSE);
-
+ if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
/* This is an absolute URL, don't allow the custom port number */
disallowport = TRUE;
- newest = malloc(newlen + 1); /* get memory for this */
- if(!newest)
- return CURLE_OUT_OF_MEMORY;
+ DEBUGASSERT(data->state.uh);
+ uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
+ (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
- strcpy_url(newest, newurl, FALSE); /* create a space-free URL */
- newurl = newest; /* use this instead now */
-
- }
+ uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
if(type == FOLLOW_FAKE) {
/* we're only figuring out the new url if we would've followed locations
@@ -1816,10 +1538,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
if(disallowport)
data->state.allow_port = FALSE;
- if(data->change.url_alloc) {
+ if(data->change.url_alloc)
Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
data->change.url = newurl;
data->change.url_alloc = TRUE;
@@ -1985,8 +1705,13 @@ CURLcode Curl_retry_request(struct connectdata *conn,
if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
struct HTTP *http = data->req.protop;
- if(http->writebytecount)
- return Curl_readrewind(conn);
+ if(http->writebytecount) {
+ CURLcode result = Curl_readrewind(conn);
+ if(result) {
+ Curl_safefree(*url);
+ return result;
+ }
+ }
}
}
return CURLE_OK;
diff --git a/Utilities/cmcurl/lib/transfer.h b/Utilities/cmcurl/lib/transfer.h
index 9ba398d27..9742455ae 100644
--- a/Utilities/cmcurl/lib/transfer.h
+++ b/Utilities/cmcurl/lib/transfer.h
@@ -51,9 +51,11 @@ int Curl_single_getsock(const struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
CURLcode Curl_readrewind(struct connectdata *conn);
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+ size_t *nreadp);
CURLcode Curl_retry_request(struct connectdata *conn, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
+CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
/* This sets up a forthcoming transfer */
void
@@ -69,4 +71,3 @@ Curl_setup_transfer (struct connectdata *data,
);
#endif /* HEADER_CURL_TRANSFER_H */
-
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 701f83ab3..0d5a13f99 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "non-ascii.h"
#include "inet_pton.h"
#include "getinfo.h"
+#include "urlapi-int.h"
/* And now for the protocols */
#include "ftp.h"
@@ -127,11 +128,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
static void conn_free(struct connectdata *conn);
static void free_fixed_hostname(struct hostname *host);
-static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
-static CURLcode parse_url_login(struct Curl_easy *data,
- struct connectdata *conn,
- char **userptr, char **passwdptr,
- char **optionsptr);
static unsigned int get_protocol_family(unsigned int protocol);
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
@@ -295,6 +291,22 @@ void Curl_freeset(struct Curl_easy *data)
Curl_mime_cleanpart(&data->set.mimepost);
}
+/* free the URL pieces */
+void Curl_up_free(struct Curl_easy *data)
+{
+ struct urlpieces *up = &data->state.up;
+ Curl_safefree(up->scheme);
+ Curl_safefree(up->hostname);
+ Curl_safefree(up->port);
+ Curl_safefree(up->user);
+ Curl_safefree(up->password);
+ Curl_safefree(up->options);
+ Curl_safefree(up->path);
+ Curl_safefree(up->query);
+ curl_url_cleanup(data->state.uh);
+ data->state.uh = NULL;
+}
+
/*
* This is the internal function curl_easy_cleanup() calls. This should
* cleanup and free all resources associated with this sessionhandle.
@@ -314,16 +326,17 @@ CURLcode Curl_close(struct Curl_easy *data)
Curl_expire_clear(data); /* shut off timers */
m = data->multi;
-
if(m)
/* This handle is still part of a multi handle, take care of this first
and detach this handle from there. */
curl_multi_remove_handle(data->multi, data);
- if(data->multi_easy)
+ if(data->multi_easy) {
/* when curl_easy_perform() is used, it creates its own multi handle to
use and this is the one */
curl_multi_cleanup(data->multi_easy);
+ data->multi_easy = NULL;
+ }
/* Destroy the timeout list that is held in the easy handle. It is
/normally/ done by curl_multi_remove_handle() but this is "just in
@@ -337,10 +350,6 @@ CURLcode Curl_close(struct Curl_easy *data)
if(data->state.rangestringalloc)
free(data->state.range);
- /* Free the pathbuffer */
- Curl_safefree(data->state.pathbuffer);
- data->state.path = NULL;
-
/* freed here just in case DONE wasn't called */
Curl_free_request_state(data);
@@ -360,19 +369,12 @@ CURLcode Curl_close(struct Curl_easy *data)
}
data->change.referer = NULL;
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
- data->change.url = NULL;
-
+ Curl_up_free(data);
Curl_safefree(data->state.buffer);
Curl_safefree(data->state.headerbuff);
-
+ Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, 1);
-
Curl_digest_cleanup(data);
-
Curl_safefree(data->info.contenttype);
Curl_safefree(data->info.wouldredirect);
@@ -519,24 +521,28 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->wildcard_enabled = FALSE;
set->chunk_bgn = ZERO_NULL;
set->chunk_end = ZERO_NULL;
-
- /* tcp keepalives are disabled by default, but provide reasonable values for
- * the interval and idle times.
- */
set->tcp_keepalive = FALSE;
set->tcp_keepintvl = 60;
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
-
set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
-
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->upload_buffer_size = UPLOADBUFFER_DEFAULT;
set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
-
+ set->fnmatch = ZERO_NULL;
+ set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
+ set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+ set->httpversion =
+#ifdef USE_NGHTTP2
+ CURL_HTTP_VERSION_2TLS
+#else
+ CURL_HTTP_VERSION_1_1
+#endif
+ ;
Curl_http2_init_userset(set);
return result;
}
@@ -596,8 +602,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
- data->set.fnmatch = ZERO_NULL;
- data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
Curl_http2_init_state(&data->state);
}
@@ -734,20 +738,23 @@ static void conn_free(struct connectdata *conn)
* primary connection, like when freeing room in the connection cache or
* killing of a dead old connection.
*
+ * A connection needs an easy handle when closing down. We support this passed
+ * in separately since the connection to get closed here is often already
+ * disassociated from an easy handle.
+ *
* This function MUST NOT reset state in the Curl_easy struct if that
* isn't strictly bound to the life-time of *this* particular connection.
*
*/
-CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
+CURLcode Curl_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
- struct Curl_easy *data;
if(!conn)
return CURLE_OK; /* this is closed and fine already */
- data = conn->data;
if(!data) {
- DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
+ DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
return CURLE_OK;
}
@@ -755,13 +762,12 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
* If this connection isn't marked to force-close, leave it open if there
* are other users of it
*/
- if(!conn->bits.close &&
- (conn->send_pipe.size + conn->recv_pipe.size)) {
- DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
- conn->send_pipe.size + conn->recv_pipe.size));
+ if(CONN_INUSE(conn) && !dead_connection) {
+ DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
return CURLE_OK;
}
+ conn->data = data;
if(conn->dns_entry != NULL) {
Curl_resolv_unlock(data, conn->dns_entry);
conn->dns_entry = NULL;
@@ -787,16 +793,12 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
free_fixed_hostname(&conn->http_proxy.host);
free_fixed_hostname(&conn->socks_proxy.host);
+ DEBUGASSERT(conn->data == data);
+ /* this assumes that the pointer is still there after the connection was
+ detected from the cache */
Curl_ssl_close(conn, FIRSTSOCKET);
- /* Indicate to all handles on the pipe that we're dead */
- if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
- signalPipeClose(&conn->send_pipe, TRUE);
- signalPipeClose(&conn->recv_pipe, TRUE);
- }
-
conn_free(conn);
-
return CURLE_OK;
}
@@ -848,6 +850,7 @@ static int IsPipeliningPossible(const struct Curl_easy *handle,
return avail;
}
+/* Returns non-zero if a handle was removed */
int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline)
{
@@ -884,6 +887,16 @@ static void Curl_printPipeline(struct curl_llist *pipeline)
static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
{
struct curl_llist_element *curr = pipeline->head;
+#ifdef DEBUGBUILD
+ {
+ struct curl_llist_element *p = pipeline->head;
+ while(p) {
+ struct Curl_easy *e = p->ptr;
+ DEBUGASSERT(GOOD_EASY_HANDLE(e));
+ p = p->next;
+ }
+ }
+#endif
if(curr) {
return (struct Curl_easy *) curr->ptr;
}
@@ -896,41 +909,22 @@ static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
void Curl_getoff_all_pipelines(struct Curl_easy *data,
struct connectdata *conn)
{
- bool recv_head = (conn->readchannel_inuse &&
- Curl_recvpipe_head(data, conn));
- bool send_head = (conn->writechannel_inuse &&
- Curl_sendpipe_head(data, conn));
-
- if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
- Curl_pipeline_leave_read(conn);
- if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
- Curl_pipeline_leave_write(conn);
-}
-
-static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
-{
- struct curl_llist_element *curr;
-
- if(!pipeline)
+ if(!conn->bundle)
return;
+ if(conn->bundle->multiuse == BUNDLE_PIPELINING) {
+ bool recv_head = (conn->readchannel_inuse &&
+ Curl_recvpipe_head(data, conn));
+ bool send_head = (conn->writechannel_inuse &&
+ Curl_sendpipe_head(data, conn));
- curr = pipeline->head;
- while(curr) {
- struct curl_llist_element *next = curr->next;
- struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
-
-#ifdef DEBUGBUILD /* debug-only code */
- if(data->magic != CURLEASY_MAGIC_NUMBER) {
- /* MAJOR BADNESS */
- infof(data, "signalPipeClose() found BAAD easy handle\n");
- }
-#endif
-
- if(pipe_broke)
- data->state.pipe_broke = TRUE;
- Curl_multi_handlePipeBreak(data);
- Curl_llist_remove(pipeline, curr, NULL);
- curr = next;
+ if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
+ Curl_pipeline_leave_read(conn);
+ if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
+ Curl_pipeline_leave_write(conn);
+ }
+ else {
+ (void)Curl_removeHandleFromPipeline(data, &conn->recv_pipe);
+ (void)Curl_removeHandleFromPipeline(data, &conn->send_pipe);
}
}
@@ -959,12 +953,13 @@ static bool extract_if_dead(struct connectdata *conn,
struct Curl_easy *data)
{
size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
- if(!pipeLen && !conn->inuse) {
+ if(!pipeLen && !CONN_INUSE(conn)) {
/* The check for a dead socket makes sense only if there are no
handles in pipeline and the connection isn't already marked in
use */
bool dead;
+ conn->data = data;
if(conn->handler->connection_check) {
/* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */
@@ -979,9 +974,9 @@ static bool extract_if_dead(struct connectdata *conn,
}
if(dead) {
- conn->data = data;
infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
Curl_conncache_remove_conn(conn, FALSE);
+ conn->data = NULL; /* detach */
return TRUE;
}
}
@@ -1025,7 +1020,7 @@ static void prune_dead_connections(struct Curl_easy *data)
while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
call_extract_if_dead)) {
/* disconnect it */
- (void)Curl_disconnect(prune.extracted, /* dead_connection */TRUE);
+ (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
}
data->state.conn_cache->last_cleanup = now;
}
@@ -1139,7 +1134,7 @@ ConnectionExists(struct Curl_easy *data,
if(extract_if_dead(check, data)) {
/* disconnect it */
- (void)Curl_disconnect(check, /* dead_connection */TRUE);
+ (void)Curl_disconnect(data, check, /* dead_connection */TRUE);
continue;
}
@@ -1267,12 +1262,12 @@ ConnectionExists(struct Curl_easy *data,
}
}
- if(!canpipe && check->inuse)
+ if(!canpipe && CONN_INUSE(check))
/* this request can't be pipelined but the checked connection is
already in use so we skip it */
continue;
- if((check->inuse) && (check->data->multi != needle->data->multi))
+ if(CONN_INUSE(check) && (check->data->multi != needle->data->multi))
/* this could be subject for pipeline/multiplex use, but only
if they belong to the same multi handle */
continue;
@@ -1464,7 +1459,7 @@ ConnectionExists(struct Curl_easy *data,
if(chosen) {
/* mark it as used before releasing the lock */
- chosen->inuse = TRUE;
+ chosen->data = data; /* own it! */
Curl_conncache_unlock(needle);
*usethis = chosen;
return TRUE; /* yes, we found one to use! */
@@ -1554,7 +1549,11 @@ int Curl_protocol_getsock(struct connectdata *conn,
{
if(conn->handler->proto_getsock)
return conn->handler->proto_getsock(conn, socks, numsocks);
- return GETSOCK_BLANK;
+ /* Backup getsock logic. Since there is a live socket in use, we must wait
+ for it or it will be removed from watching when the multi_socket API is
+ used. */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}
int Curl_doing_getsock(struct connectdata *conn,
@@ -1838,6 +1837,12 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
/* Store creation time to help future close decision making */
conn->created = Curl_now();
+ /* Store current time to give a baseline to keepalive connection times. */
+ conn->keepalive = Curl_now();
+
+ /* Store off the configured connection upkeep time. */
+ conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
+
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
@@ -1944,30 +1949,37 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
return NULL;
}
-static CURLcode findprotocol(struct Curl_easy *data,
- struct connectdata *conn,
- const char *protostr)
+/* returns the handler if the given scheme is built-in */
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
-
- /* Scan protocol handler table and match against 'protostr' to set a few
- variables based on the URL. Now that the handler may be changed later
- when the protocol specific setup function is called. */
- for(pp = protocols; (p = *pp) != NULL; pp++) {
- if(strcasecompare(p->scheme, protostr)) {
+ /* Scan protocol handler table and match against 'scheme'. The handler may
+ be changed later when the protocol specific setup function is called. */
+ for(pp = protocols; (p = *pp) != NULL; pp++)
+ if(strcasecompare(p->scheme, scheme))
/* Protocol found in table. Check if allowed */
- if(!(data->set.allowed_protocols & p->protocol))
- /* nope, get out */
- break;
+ return p;
+ return NULL; /* not found */
+}
+
+
+static CURLcode findprotocol(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *protostr)
+{
+ const struct Curl_handler *p = Curl_builtin_scheme(protostr);
- /* it is allowed for "normal" request, now do an extra check if this is
- the result of a redirect */
- if(data->state.this_is_a_follow &&
- !(data->set.redir_protocols & p->protocol))
- /* nope, get out */
- break;
+ if(p && /* Protocol found in table. Check if allowed */
+ (data->set.allowed_protocols & p->protocol)) {
+ /* it is allowed for "normal" request, now do an extra check if this is
+ the result of a redirect */
+ if(data->state.this_is_a_follow &&
+ !(data->set.redir_protocols & p->protocol))
+ /* nope, get out */
+ ;
+ else {
/* Perform setup complement if some. */
conn->handler = conn->given = p;
@@ -1976,7 +1988,6 @@ static CURLcode findprotocol(struct Curl_easy *data,
}
}
-
/* The protocol was not found in the table, but we don't have to assign it
to anything since it is already assigned to a dummy-struct in the
create_conn() function when the connectdata struct is allocated. */
@@ -1986,379 +1997,134 @@ static CURLcode findprotocol(struct Curl_easy *data,
return CURLE_UNSUPPORTED_PROTOCOL;
}
+
+CURLcode Curl_uc_to_curlcode(CURLUcode uc)
+{
+ switch(uc) {
+ default:
+ return CURLE_URL_MALFORMAT;
+ case CURLUE_UNSUPPORTED_SCHEME:
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ case CURLUE_OUT_OF_MEMORY:
+ return CURLE_OUT_OF_MEMORY;
+ case CURLUE_USER_NOT_ALLOWED:
+ return CURLE_LOGIN_DENIED;
+ }
+}
+
/*
* Parse URL and fill in the relevant members of the connection struct.
*/
static CURLcode parseurlandfillconn(struct Curl_easy *data,
- struct connectdata *conn,
- bool *prot_missing,
- char **userp, char **passwdp,
- char **optionsp)
+ struct connectdata *conn)
{
- char *at;
- char *fragment;
- char *path = data->state.path;
- char *query;
- int i;
- int rc;
- const char *protop = "";
CURLcode result;
- bool rebuild_url = FALSE;
- bool url_has_scheme = FALSE;
- char protobuf[16];
-
- *prot_missing = FALSE;
+ CURLU *uh;
+ CURLUcode uc;
+ char *hostname;
- /* We might pass the entire URL into the request so we need to make sure
- * there are no bad characters in there.*/
- if(strpbrk(data->change.url, "\r\n")) {
- failf(data, "Illegal characters found in URL");
- return CURLE_URL_MALFORMAT;
- }
+ Curl_up_free(data); /* cleanup previous leftovers first */
- /*************************************************************
- * Parse the URL.
- *
- * We need to parse the url even when using the proxy, because we will need
- * the hostname and port in case we are trying to SSL connect through the
- * proxy -- and we don't know if we will need to use SSL until we parse the
- * url ...
- ************************************************************/
- if(data->change.url[0] == ':') {
- failf(data, "Bad URL, colon is first character");
- return CURLE_URL_MALFORMAT;
- }
+ /* parse the URL */
+ uh = data->state.uh = curl_url();
+ if(!uh)
+ return CURLE_OUT_OF_MEMORY;
- /* MSDOS/Windows style drive prefix, eg c: in c:foo */
-#define STARTS_WITH_DRIVE_PREFIX(str) \
- ((('a' <= str[0] && str[0] <= 'z') || \
- ('A' <= str[0] && str[0] <= 'Z')) && \
- (str[1] == ':'))
-
- /* MSDOS/Windows style drive prefix, optionally with
- * a '|' instead of ':', followed by a slash or NUL */
-#define STARTS_WITH_URL_DRIVE_PREFIX(str) \
- ((('a' <= (str)[0] && (str)[0] <= 'z') || \
- ('A' <= (str)[0] && (str)[0] <= 'Z')) && \
- ((str)[1] == ':' || (str)[1] == '|') && \
- ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0))
-
- /* Don't mistake a drive letter for a scheme if the default protocol is file.
- curld --proto-default file c:/foo/bar.txt */
- if(STARTS_WITH_DRIVE_PREFIX(data->change.url) &&
- data->set.str[STRING_DEFAULT_PROTOCOL] &&
- strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file")) {
- ; /* do nothing */
- }
- else { /* check for a scheme */
- for(i = 0; i < 16 && data->change.url[i]; ++i) {
- if(data->change.url[i] == '/')
- break;
- if(data->change.url[i] == ':') {
- url_has_scheme = TRUE;
- break;
- }
- }
+ if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
+ !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
+ char *url;
+ if(data->change.url_alloc)
+ free(data->change.url);
+ url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
+ data->change.url);
+ if(!url)
+ return CURLE_OUT_OF_MEMORY;
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
}
- /* handle the file: scheme */
- if((url_has_scheme && strncasecompare(data->change.url, "file:", 5)) ||
- (!url_has_scheme && data->set.str[STRING_DEFAULT_PROTOCOL] &&
- strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file"))) {
- if(url_has_scheme)
- rc = sscanf(data->change.url, "%*15[^\n/:]:%[^\n]", path);
- else
- rc = sscanf(data->change.url, "%[^\n]", path);
-
- if(rc != 1) {
- failf(data, "Bad URL");
- return CURLE_URL_MALFORMAT;
- }
-
- /* Extra handling URLs with an authority component (i.e. that start with
- * "file://")
- *
- * We allow omitted hostname (e.g. file:/<path>) -- valid according to
- * RFC 8089, but not the (current) WHAT-WG URL spec.
- */
- if(url_has_scheme && path[0] == '/' && path[1] == '/') {
- /* swallow the two slashes */
- char *ptr = &path[2];
-
- /*
- * According to RFC 8089, a file: URL can be reliably dereferenced if:
- *
- * o it has no/blank hostname, or
- *
- * o the hostname matches "localhost" (case-insensitively), or
- *
- * o the hostname is a FQDN that resolves to this machine.
- *
- * For brevity, we only consider URLs with empty, "localhost", or
- * "127.0.0.1" hostnames as local.
- *
- * Additionally, there is an exception for URLs with a Windows drive
- * letter in the authority (which was accidentally omitted from RFC 8089
- * Appendix E, but believe me, it was meant to be there. --MK)
- */
- if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) {
- /* the URL includes a host name, it must match "localhost" or
- "127.0.0.1" to be valid */
- if(!checkprefix("localhost/", ptr) &&
- !checkprefix("127.0.0.1/", ptr)) {
- failf(data, "Invalid file://hostname/, "
- "expected localhost or 127.0.0.1 or none");
- return CURLE_URL_MALFORMAT;
- }
- ptr += 9; /* now points to the slash after the host */
- }
+ uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
+ CURLU_GUESS_SCHEME |
+ CURLU_NON_SUPPORT_SCHEME |
+ (data->set.disallow_username_in_url ?
+ CURLU_DISALLOW_USER : 0) |
+ (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
- /* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, ptr, strlen(ptr) + 1);
- }
+ uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
-#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
- /* Don't allow Windows drive letters when not in Windows.
- * This catches both "file:/c:" and "file:c:" */
- if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
- STARTS_WITH_URL_DRIVE_PREFIX(path)) {
- failf(data, "File drive letters are only accepted in MSDOS/Windows.");
- return CURLE_URL_MALFORMAT;
- }
-#else
- /* If the path starts with a slash and a drive letter, ditch the slash */
- if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
- /* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, &path[1], strlen(&path[1]) + 1);
- }
-#endif
+ result = findprotocol(data, conn, data->state.up.scheme);
+ if(result)
+ return result;
- protop = "file"; /* protocol string */
- *prot_missing = !url_has_scheme;
+ uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
+ CURLU_URLDECODE);
+ if(!uc) {
+ conn->user = strdup(data->state.up.user);
+ if(!conn->user)
+ return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE;
}
- else {
- /* clear path */
- char slashbuf[4];
- path[0] = 0;
-
- rc = sscanf(data->change.url,
- "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
- protobuf, slashbuf, conn->host.name, path);
- if(2 == rc) {
- failf(data, "Bad URL");
- return CURLE_URL_MALFORMAT;
- }
- if(3 > rc) {
-
- /*
- * The URL was badly formatted, let's try the browser-style _without_
- * protocol specified like 'http://'.
- */
- rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
- if(1 > rc) {
- /*
- * We couldn't even get this format.
- * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
- * assigned, but the return value is EOF!
- */
-#if defined(__DJGPP__) && (DJGPP_MINOR == 4)
- if(!(rc == -1 && *conn->host.name))
-#endif
- {
- failf(data, "<url> malformed");
- return CURLE_URL_MALFORMAT;
- }
- }
-
- /*
- * Since there was no protocol part specified in the URL use the
- * user-specified default protocol. If we weren't given a default make a
- * guess by matching some protocols against the host's outermost
- * sub-domain name. Finally if there was no match use HTTP.
- */
-
- protop = data->set.str[STRING_DEFAULT_PROTOCOL];
- if(!protop) {
- /* Note: if you add a new protocol, please update the list in
- * lib/version.c too! */
- if(checkprefix("FTP.", conn->host.name))
- protop = "ftp";
- else if(checkprefix("DICT.", conn->host.name))
- protop = "DICT";
- else if(checkprefix("LDAP.", conn->host.name))
- protop = "LDAP";
- else if(checkprefix("IMAP.", conn->host.name))
- protop = "IMAP";
- else if(checkprefix("SMTP.", conn->host.name))
- protop = "smtp";
- else if(checkprefix("POP3.", conn->host.name))
- protop = "pop3";
- else
- protop = "http";
- }
+ else if(uc != CURLUE_NO_USER)
+ return Curl_uc_to_curlcode(uc);
- *prot_missing = TRUE; /* not given in URL */
- }
- else {
- size_t s = strlen(slashbuf);
- protop = protobuf;
- if(s != 2) {
- infof(data, "Unwillingly accepted illegal URL using %d slash%s!\n",
- s, s>1?"es":"");
-
- if(data->change.url_alloc)
- free(data->change.url);
- /* repair the URL to use two slashes */
- data->change.url = aprintf("%s://%s%s",
- protobuf, conn->host.name, path);
- if(!data->change.url)
- return CURLE_OUT_OF_MEMORY;
- data->change.url_alloc = TRUE;
- }
- }
+ uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
+ CURLU_URLDECODE);
+ if(!uc) {
+ conn->passwd = strdup(data->state.up.password);
+ if(!conn->passwd)
+ return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE;
}
+ else if(uc != CURLUE_NO_PASSWORD)
+ return Curl_uc_to_curlcode(uc);
- /* We search for '?' in the host name (but only on the right side of a
- * @-letter to allow ?-letters in username and password) to handle things
- * like http://example.com?param= (notice the missing '/').
- */
- at = strchr(conn->host.name, '@');
- if(at)
- query = strchr(at + 1, '?');
- else
- query = strchr(conn->host.name, '?');
-
- if(query) {
- /* We must insert a slash before the '?'-letter in the URL. If the URL had
- a slash after the '?', that is where the path currently begins and the
- '?string' is still part of the host name.
-
- We must move the trailing part from the host name and put it first in
- the path. And have it all prefixed with a slash.
- */
-
- size_t hostlen = strlen(query);
- size_t pathlen = strlen(path);
-
- /* move the existing path plus the zero byte forward, to make room for
- the host-name part */
- memmove(path + hostlen + 1, path, pathlen + 1);
-
- /* now copy the trailing host part in front of the existing path */
- memcpy(path + 1, query, hostlen);
-
- path[0]='/'; /* prepend the missing slash */
- rebuild_url = TRUE;
-
- *query = 0; /* now cut off the hostname at the ? */
- }
- else if(!path[0]) {
- /* if there's no path set, use a single slash */
- strcpy(path, "/");
- rebuild_url = TRUE;
+ uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
+ CURLU_URLDECODE);
+ if(!uc) {
+ conn->options = strdup(data->state.up.options);
+ if(!conn->options)
+ return CURLE_OUT_OF_MEMORY;
}
+ else if(uc != CURLUE_NO_OPTIONS)
+ return Curl_uc_to_curlcode(uc);
- /* If the URL is malformatted (missing a '/' after hostname before path) we
- * insert a slash here. The only letters except '/' that can start a path is
- * '?' and '#' - as controlled by the two sscanf() patterns above.
- */
- if(path[0] != '/') {
- /* We need this function to deal with overlapping memory areas. We know
- that the memory area 'path' points to is 'urllen' bytes big and that
- is bigger than the path. Use +1 to move the zero byte too. */
- memmove(&path[1], path, strlen(path) + 1);
- path[0] = '/';
- rebuild_url = TRUE;
- }
- else if(!data->set.path_as_is) {
- /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
- char *newp = Curl_dedotdotify(path);
- if(!newp)
+ uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
+ if(uc) {
+ if(!strcasecompare("file", data->state.up.scheme))
return CURLE_OUT_OF_MEMORY;
-
- if(strcmp(newp, path)) {
- rebuild_url = TRUE;
- free(data->state.pathbuffer);
- data->state.pathbuffer = newp;
- data->state.path = newp;
- path = newp;
- }
- else
- free(newp);
}
- /*
- * "rebuild_url" means that one or more URL components have been modified so
- * we need to generate an updated full version. We need the corrected URL
- * when communicating over HTTP proxy and we don't know at this point if
- * we're using a proxy or not.
- */
- if(rebuild_url) {
- char *reurl;
-
- size_t plen = strlen(path); /* new path, should be 1 byte longer than
- the original */
- size_t prefixlen = strlen(conn->host.name);
-
- if(!*prot_missing) {
- size_t protolen = strlen(protop);
-
- if(curl_strnequal(protop, data->change.url, protolen))
- prefixlen += protolen;
- else {
- failf(data, "<url> malformed");
- return CURLE_URL_MALFORMAT;
- }
-
- if(curl_strnequal("://", &data->change.url[protolen], 3))
- prefixlen += 3;
- /* only file: is allowed to omit one or both slashes */
- else if(curl_strnequal("file:", data->change.url, 5))
- prefixlen += 1 + (data->change.url[5] == '/');
- else {
- failf(data, "<url> malformed");
- return CURLE_URL_MALFORMAT;
- }
- }
+ uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
- reurl = malloc(prefixlen + plen + 1);
- if(!reurl)
+ uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
+ CURLU_DEFAULT_PORT);
+ if(uc) {
+ if(!strcasecompare("file", data->state.up.scheme))
return CURLE_OUT_OF_MEMORY;
-
- /* copy the prefix */
- memcpy(reurl, data->change.url, prefixlen);
-
- /* append the trailing piece + zerobyte */
- memcpy(&reurl[prefixlen], path, plen + 1);
-
- /* possible free the old one */
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
-
- infof(data, "Rebuilt URL to: %s\n", reurl);
-
- data->change.url = reurl;
- data->change.url_alloc = TRUE; /* free this later */
+ }
+ else {
+ unsigned long port = strtoul(data->state.up.port, NULL, 10);
+ conn->remote_port = curlx_ultous(port);
}
- result = findprotocol(data, conn, protop);
- if(result)
- return result;
+ (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
- /*
- * Parse the login details from the URL and strip them out of
- * the host name
- */
- result = parse_url_login(data, conn, userp, passwdp, optionsp);
- if(result)
- return result;
+ hostname = data->state.up.hostname;
+ if(!hostname)
+ /* this is for file:// transfers, get a dummy made */
+ hostname = (char *)"";
- if(conn->host.name[0] == '[') {
+ if(hostname[0] == '[') {
/* This looks like an IPv6 address literal. See if there is an address
- scope if there is no location header */
- char *percent = strchr(conn->host.name, '%');
+ scope. */
+ char *percent = strchr(++hostname, '%');
+ conn->bits.ipv6_ip = TRUE;
if(percent) {
unsigned int identifier_offset = 3;
char *endp;
@@ -2406,33 +2172,22 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
infof(data, "Invalid IPv6 address format\n");
}
}
+ percent = strchr(hostname, ']');
+ if(percent)
+ /* terminate IPv6 numerical at end bracket */
+ *percent = 0;
}
+ /* make sure the connect struct gets its own copy of the host name */
+ conn->host.rawalloc = strdup(hostname);
+ if(!conn->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ conn->host.name = conn->host.rawalloc;
+
if(data->set.scope_id)
/* Override any scope that was set above. */
conn->scope_id = data->set.scope_id;
- /* Remove the fragment part of the path. Per RFC 2396, this is always the
- last part of the URI. We are looking for the first '#' so that we deal
- gracefully with non conformant URI such as http://example.com#foo#bar. */
- fragment = strchr(path, '#');
- if(fragment) {
- *fragment = 0;
-
- /* we know the path part ended with a fragment, so we know the full URL
- string does too and we need to cut it off from there so it isn't used
- over proxy */
- fragment = strchr(data->change.url, '#');
- if(fragment)
- *fragment = 0;
- }
-
- /*
- * So if the URL was A://B/C#D,
- * protop is A
- * conn->host.name is B
- * data->state.path is /C
- */
return CURLE_OK;
}
@@ -2449,7 +2204,7 @@ static CURLcode setup_range(struct Curl_easy *data)
free(s->range);
if(s->resume_from)
- s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
+ s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
else
s->range = strdup(data->set.str[STRING_SET_RANGE]);
@@ -2481,18 +2236,6 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
{
const struct Curl_handler * p;
CURLcode result;
- struct Curl_easy *data = conn->data;
-
- /* in some case in the multi state-machine, we go back to the CONNECT state
- and then a second (or third or...) call to this function will be made
- without doing a DISCONNECT or DONE in between (since the connection is
- yet in place) and therefore this function needs to first make sure
- there's no lingering previous data allocated. */
- Curl_free_request_state(data);
-
- memset(&data->req, 0, sizeof(struct SingleRequest));
- data->req.maxdownload = -1;
-
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
/* Perform setup complement if some. */
@@ -2539,14 +2282,13 @@ static bool check_noproxy(const char *name, const char *no_proxy)
* not be proxied, or an asterisk to override
* all proxy variables)
*/
- size_t tok_start;
- size_t tok_end;
- const char *separator = ", ";
- size_t no_proxy_len;
- size_t namelen;
- char *endptr;
-
if(no_proxy && no_proxy[0]) {
+ size_t tok_start;
+ size_t tok_end;
+ const char *separator = ", ";
+ size_t no_proxy_len;
+ size_t namelen;
+ char *endptr;
if(strcasecompare("*", no_proxy)) {
return TRUE;
}
@@ -2560,11 +2302,8 @@ static bool check_noproxy(const char *name, const char *no_proxy)
if(!endptr)
return FALSE;
name++;
- }
- else
- endptr = strchr(name, ':');
- if(endptr)
namelen = endptr - name;
+ }
else
namelen = strlen(name);
@@ -3097,124 +2836,6 @@ out:
#endif /* CURL_DISABLE_PROXY */
/*
- * parse_url_login()
- *
- * Parse the login details (user name, password and options) from the URL and
- * strip them out of the host name
- *
- * Inputs: data->set.use_netrc (CURLOPT_NETRC)
- * conn->host.name
- *
- * Outputs: (almost :- all currently undefined)
- * conn->bits.user_passwd - non-zero if non-default passwords exist
- * user - non-zero length if defined
- * passwd - non-zero length if defined
- * options - non-zero length if defined
- * conn->host.name - remove user name and password
- */
-static CURLcode parse_url_login(struct Curl_easy *data,
- struct connectdata *conn,
- char **user, char **passwd, char **options)
-{
- CURLcode result = CURLE_OK;
- char *userp = NULL;
- char *passwdp = NULL;
- char *optionsp = NULL;
-
- /* At this point, we're hoping all the other special cases have
- * been taken care of, so conn->host.name is at most
- * [user[:password][;options]]@]hostname
- *
- * We need somewhere to put the embedded details, so do that first.
- */
-
- char *ptr = strchr(conn->host.name, '@');
- char *login = conn->host.name;
-
- DEBUGASSERT(!**user);
- DEBUGASSERT(!**passwd);
- DEBUGASSERT(!**options);
- DEBUGASSERT(conn->handler);
-
- if(!ptr)
- goto out;
-
- /* We will now try to extract the
- * possible login information in a string like:
- * ftp://user:password@ftp.my.site:8021/README */
- conn->host.name = ++ptr;
-
- /* So the hostname is sane. Only bother interpreting the
- * results if we could care. It could still be wasted
- * work because it might be overtaken by the programmatically
- * set user/passwd, but doing that first adds more cases here :-(
- */
-
- if(data->set.use_netrc == CURL_NETRC_REQUIRED)
- goto out;
-
- /* We could use the login information in the URL so extract it. Only parse
- options if the handler says we should. */
- result =
- Curl_parse_login_details(login, ptr - login - 1,
- &userp, &passwdp,
- (conn->handler->flags & PROTOPT_URLOPTIONS)?
- &optionsp:NULL);
- if(result)
- goto out;
-
- if(userp) {
- char *newname;
-
- /* We have a user in the URL */
- conn->bits.userpwd_in_url = TRUE;
- conn->bits.user_passwd = TRUE; /* enable user+password */
-
- /* Decode the user */
- result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
- if(result) {
- goto out;
- }
-
- free(*user);
- *user = newname;
- }
-
- if(passwdp) {
- /* We have a password in the URL so decode it */
- char *newpasswd;
- result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
- if(result) {
- goto out;
- }
-
- free(*passwd);
- *passwd = newpasswd;
- }
-
- if(optionsp) {
- /* We have an options list in the URL so decode it */
- char *newoptions;
- result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
- if(result) {
- goto out;
- }
-
- free(*options);
- *options = newoptions;
- }
-
-
- out:
-
- free(userp);
- free(passwdp);
- free(optionsp);
-
- return result;
-}
-
-/*
* Curl_parse_login_details()
*
* This is used to parse a login string for user name, password and options in
@@ -3236,7 +2857,7 @@ static CURLcode parse_url_login(struct Curl_easy *data,
* len [in] - The length of the login string.
* userp [in/out] - The address where a pointer to newly allocated memory
* holding the user will be stored upon completion.
- * passdwp [in/out] - The address where a pointer to newly allocated memory
+ * passwdp [in/out] - The address where a pointer to newly allocated memory
* holding the password will be stored upon completion.
* optionsp [in/out] - The address where a pointer to newly allocated memory
* holding the options will be stored upon completion.
@@ -3347,131 +2968,23 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
* No matter if we use a proxy or not, we have to figure out the remote
* port number of various reasons.
*
- * To be able to detect port number flawlessly, we must not confuse them
- * IPv6-specified addresses in the [0::1] style. (RFC2732)
- *
- * The conn->host.name is currently [user:passwd@]host[:port] where host
- * could be a hostname, IPv4 address or IPv6 address.
- *
* The port number embedded in the URL is replaced, if necessary.
*************************************************************/
static CURLcode parse_remote_port(struct Curl_easy *data,
struct connectdata *conn)
{
- char *portptr;
- char endbracket;
-
- /* Note that at this point, the IPv6 address cannot contain any scope
- suffix as that has already been removed in the parseurlandfillconn()
- function */
- if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
- &endbracket)) &&
- (']' == endbracket)) {
- /* this is a RFC2732-style specified IP-address */
- conn->bits.ipv6_ip = TRUE;
-
- conn->host.name++; /* skip over the starting bracket */
- portptr = strchr(conn->host.name, ']');
- if(portptr) {
- *portptr++ = '\0'; /* zero terminate, killing the bracket */
- if(*portptr) {
- if (*portptr != ':') {
- failf(data, "IPv6 closing bracket followed by '%c'", *portptr);
- return CURLE_URL_MALFORMAT;
- }
- }
- else
- portptr = NULL; /* no port number available */
- }
- }
- else {
-#ifdef ENABLE_IPV6
- struct in6_addr in6;
- if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
- /* This is a numerical IPv6 address, meaning this is a wrongly formatted
- URL */
- failf(data, "IPv6 numerical address used in URL without brackets");
- return CURLE_URL_MALFORMAT;
- }
-#endif
-
- portptr = strchr(conn->host.name, ':');
- }
if(data->set.use_port && data->state.allow_port) {
- /* if set, we use this and ignore the port possibly given in the URL */
+ /* if set, we use this instead of the port possibly given in the URL */
+ char portbuf[16];
+ CURLUcode uc;
conn->remote_port = (unsigned short)data->set.use_port;
- if(portptr)
- *portptr = '\0'; /* cut off the name there anyway - if there was a port
- number - since the port number is to be ignored! */
- if(conn->bits.httpproxy) {
- /* we need to create new URL with the new port number */
- char *url;
- char type[12]="";
-
- if(conn->bits.type_set)
- snprintf(type, sizeof(type), ";type=%c",
- data->set.prefer_ascii?'A':
- (data->set.ftp_list_only?'D':'I'));
-
- /*
- * This synthesized URL isn't always right--suffixes like ;type=A are
- * 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:%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,
- type);
- if(!url)
- return CURLE_OUT_OF_MEMORY;
-
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
-
- data->change.url = url;
- data->change.url_alloc = TRUE;
- }
- }
- else if(portptr) {
- /* no CURLOPT_PORT given, extract the one from the URL */
-
- char *rest;
- long port;
-
- port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
-
- if((port < 0) || (port > 0xffff)) {
- /* Single unix standard says port numbers are 16 bits long */
- failf(data, "Port number out of range");
- return CURLE_URL_MALFORMAT;
- }
-
- if(rest[0]) {
- failf(data, "Port number ended with '%c'", rest[0]);
- return CURLE_URL_MALFORMAT;
- }
-
- if(rest != &portptr[1]) {
- *portptr = '\0'; /* cut off the name there */
- conn->remote_port = curlx_ultous(port);
- }
- else {
- /* Browser behavior adaptation. If there's a colon with no digits after,
- just cut off the name there which makes us ignore the colon and just
- use the default port. Firefox and Chrome both do that. */
- *portptr = '\0';
- }
+ snprintf(portbuf, sizeof(portbuf), "%u", conn->remote_port);
+ uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
+ if(uc)
+ return CURLE_OUT_OF_MEMORY;
}
- /* only if remote_port was not already parsed off the URL we use the
- default port number */
- if(conn->remote_port < 0)
- conn->remote_port = (unsigned short)conn->given->defport;
-
return CURLE_OK;
}
@@ -3483,11 +2996,16 @@ static CURLcode override_login(struct Curl_easy *data,
struct connectdata *conn,
char **userp, char **passwdp, char **optionsp)
{
+ bool user_changed = FALSE;
+ bool passwd_changed = FALSE;
+ CURLUcode uc;
if(data->set.str[STRING_USERNAME]) {
free(*userp);
*userp = strdup(data->set.str[STRING_USERNAME]);
if(!*userp)
return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+ user_changed = TRUE;
}
if(data->set.str[STRING_PASSWORD]) {
@@ -3495,6 +3013,8 @@ static CURLcode override_login(struct Curl_easy *data,
*passwdp = strdup(data->set.str[STRING_PASSWORD]);
if(!*passwdp)
return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+ passwd_changed = TRUE;
}
if(data->set.str[STRING_OPTIONS]) {
@@ -3506,9 +3026,16 @@ static CURLcode override_login(struct Curl_easy *data,
conn->bits.netrc = FALSE;
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
- int ret = Curl_parsenetrc(conn->host.name,
- userp, passwdp,
- data->set.str[STRING_NETRC_FILE]);
+ char *nuser = NULL;
+ char *npasswd = NULL;
+ int ret;
+
+ if(data->set.use_netrc == CURL_NETRC_OPTIONAL)
+ nuser = *userp; /* to separate otherwise identical machines */
+
+ ret = Curl_parsenetrc(conn->host.name,
+ &nuser, &npasswd,
+ data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the "
DOT_CHAR "netrc file; using defaults\n",
@@ -3522,55 +3049,85 @@ static CURLcode override_login(struct Curl_easy *data,
file, so that it is safe to use even if we followed a Location: to a
different host or similar. */
conn->bits.netrc = TRUE;
-
conn->bits.user_passwd = TRUE; /* enable user+password */
+
+ if(data->set.use_netrc == CURL_NETRC_OPTIONAL) {
+ /* prefer credentials outside netrc */
+ if(nuser && !*userp) {
+ free(*userp);
+ *userp = nuser;
+ user_changed = TRUE;
+ }
+ if(npasswd && !*passwdp) {
+ free(*passwdp);
+ *passwdp = npasswd;
+ passwd_changed = TRUE;
+ }
+ }
+ else {
+ /* prefer netrc credentials */
+ if(nuser) {
+ free(*userp);
+ *userp = nuser;
+ user_changed = TRUE;
+ }
+ if(npasswd) {
+ free(*passwdp);
+ *passwdp = npasswd;
+ passwd_changed = TRUE;
+ }
+ }
}
}
+ /* for updated strings, we update them in the URL */
+ if(user_changed) {
+ uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ }
+ if(passwd_changed) {
+ uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ }
return CURLE_OK;
}
/*
* Set the login details so they're available in the connection
*/
-static CURLcode set_login(struct connectdata *conn,
- const char *user, const char *passwd,
- const char *options)
+static CURLcode set_login(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
+ const char *setuser = CURL_DEFAULT_USER;
+ const char *setpasswd = CURL_DEFAULT_PASSWORD;
/* If our protocol needs a password and we have none, use the defaults */
- if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
- /* Store the default user */
- conn->user = strdup(CURL_DEFAULT_USER);
-
- /* Store the default password */
- if(conn->user)
- conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
- else
- conn->passwd = NULL;
-
- /* This is the default password, so DON'T set conn->bits.user_passwd */
- }
+ if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
+ ;
else {
- /* Store the user, zero-length if not set */
- conn->user = strdup(user);
-
- /* Store the password (only if user is present), zero-length if not set */
- if(conn->user)
- conn->passwd = strdup(passwd);
- else
- conn->passwd = NULL;
+ setuser = "";
+ setpasswd = "";
+ }
+ /* Store the default user */
+ if(!conn->user) {
+ conn->user = strdup(setuser);
+ if(!conn->user)
+ return CURLE_OUT_OF_MEMORY;
}
- if(!conn->user || !conn->passwd)
- result = CURLE_OUT_OF_MEMORY;
-
- /* Store the options, null if not set */
- if(!result && options[0]) {
- conn->options = strdup(options);
+ /* Store the default password */
+ if(!conn->passwd) {
+ conn->passwd = strdup(setpasswd);
+ if(!conn->passwd)
+ result = CURLE_OUT_OF_MEMORY;
+ }
- if(!conn->options)
+ /* if there's a user without password, consider password blank */
+ if(conn->user && !conn->passwd) {
+ conn->passwd = strdup("");
+ if(!conn->passwd)
result = CURLE_OUT_OF_MEMORY;
}
@@ -3982,6 +3539,7 @@ static void reuse_conn(struct connectdata *old_conn,
Curl_safefree(old_conn->user);
Curl_safefree(old_conn->passwd);
+ Curl_safefree(old_conn->options);
Curl_safefree(old_conn->http_proxy.user);
Curl_safefree(old_conn->socks_proxy.user);
Curl_safefree(old_conn->http_proxy.passwd);
@@ -4021,12 +3579,7 @@ static CURLcode create_conn(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn;
struct connectdata *conn_temp = NULL;
- size_t urllen;
- char *user = NULL;
- char *passwd = NULL;
- char *options = NULL;
bool reuse;
- bool prot_missing = FALSE;
bool connections_available = TRUE;
bool force_reuse = FALSE;
bool waitpipe = FALSE;
@@ -4038,7 +3591,6 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* Check input data
*************************************************************/
-
if(!data->change.url) {
result = CURLE_URL_MALFORMAT;
goto out;
@@ -4060,107 +3612,10 @@ static CURLcode create_conn(struct Curl_easy *data,
any failure */
*in_connect = conn;
- /* This initing continues below, see the comment "Continue connectdata
- * initialization here" */
-
- /***********************************************************
- * We need to allocate memory to store the path in. We get the size of the
- * full URL to be sure, and we need to make it at least 256 bytes since
- * other parts of the code will rely on this fact
- ***********************************************************/
-#define LEAST_PATH_ALLOC 256
- urllen = strlen(data->change.url);
- if(urllen < LEAST_PATH_ALLOC)
- urllen = LEAST_PATH_ALLOC;
-
- /*
- * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
- * 1 - an extra terminating zero
- * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
- */
-
- Curl_safefree(data->state.pathbuffer);
- data->state.path = NULL;
-
- data->state.pathbuffer = malloc(urllen + 2);
- if(NULL == data->state.pathbuffer) {
- result = CURLE_OUT_OF_MEMORY; /* really bad error */
- goto out;
- }
- data->state.path = data->state.pathbuffer;
-
- conn->host.rawalloc = malloc(urllen + 2);
- if(NULL == conn->host.rawalloc) {
- Curl_safefree(data->state.pathbuffer);
- data->state.path = NULL;
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- conn->host.name = conn->host.rawalloc;
- conn->host.name[0] = 0;
-
- user = strdup("");
- passwd = strdup("");
- options = strdup("");
- if(!user || !passwd || !options) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
- &options);
+ result = parseurlandfillconn(data, conn);
if(result)
goto out;
- /*************************************************************
- * No protocol part in URL was used, add it!
- *************************************************************/
- if(prot_missing) {
- /* We're guessing prefixes here and if we're told to use a proxy or if
- 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;
-
- reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
-
- if(!reurl) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- /* Change protocol prefix to lower-case */
- for(ch_lower = reurl; *ch_lower != ':'; ch_lower++)
- *ch_lower = (char)TOLOWER(*ch_lower);
-
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
-
- data->change.url = reurl;
- data->change.url_alloc = TRUE; /* free this later */
- }
-
- /*************************************************************
- * If the protocol can't handle url query strings, then cut
- * off the unhandable part
- *************************************************************/
- if((conn->given->flags&PROTOPT_NOURLQUERY)) {
- char *path_q_sep = strchr(conn->data->state.path, '?');
- if(path_q_sep) {
- /* according to rfc3986, allow the query (?foo=bar)
- also on protocols that can't handle it.
-
- cut the string-part after '?'
- */
-
- /* terminate the string */
- path_q_sep[0] = 0;
- }
- }
-
if(data->set.str[STRING_BEARER]) {
conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
if(!conn->oauth_bearer) {
@@ -4204,10 +3659,12 @@ static CURLcode create_conn(struct Curl_easy *data,
/* Check for overridden login details and set them accordingly so they
they are known when protocol->setup_connection is called! */
- result = override_login(data, conn, &user, &passwd, &options);
+ result = override_login(data, conn, &conn->user, &conn->passwd,
+ &conn->options);
if(result)
goto out;
- result = set_login(conn, user, passwd, options);
+
+ result = set_login(conn); /* default credentials */
if(result)
goto out;
@@ -4290,6 +3747,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* this is supposed to be the connect function so we better at least check
that the file is present here! */
DEBUGASSERT(conn->handler->connect_it);
+ Curl_persistconninfo(conn);
result = conn->handler->connect_it(conn, &done);
/* Setup a "faked" transfer that'll do nothing */
@@ -4297,7 +3755,9 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->data = data;
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
- Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ if(result)
+ goto out;
/*
* Setup whatever necessary for a resumed transfer
@@ -4343,6 +3803,10 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
data->set.proxy_ssl.primary.cipher_list =
data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+ data->set.ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
+ data->set.proxy_ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
@@ -4387,6 +3851,9 @@ static CURLcode create_conn(struct Curl_easy *data,
* new one.
*************************************************************/
+ DEBUGASSERT(conn->user);
+ DEBUGASSERT(conn->passwd);
+
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
we only acknowledge this option if this is not a re-used connection
already (which happens due to follow-location or during a HTTP
@@ -4468,13 +3935,11 @@ static CURLcode create_conn(struct Curl_easy *data,
conn_candidate = Curl_conncache_extract_bundle(data, bundle);
Curl_conncache_unlock(conn);
- if(conn_candidate) {
- /* Set the connection's owner correctly, then kill it */
- conn_candidate->data = data;
- (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
- }
+ if(conn_candidate)
+ (void)Curl_disconnect(data, conn_candidate,
+ /* dead_connection */ FALSE);
else {
- infof(data, "No more connections allowed to host: %d\n",
+ infof(data, "No more connections allowed to host: %zu\n",
max_host_connections);
connections_available = FALSE;
}
@@ -4491,12 +3956,9 @@ static CURLcode create_conn(struct Curl_easy *data,
/* The cache is full. Let's see if we can kill a connection. */
conn_candidate = Curl_conncache_extract_oldest(data);
-
- if(conn_candidate) {
- /* Set the connection's owner correctly, then kill it */
- conn_candidate->data = data;
- (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
- }
+ if(conn_candidate)
+ (void)Curl_disconnect(data, conn_candidate,
+ /* dead_connection */ FALSE);
else {
infof(data, "No connections available in cache\n");
connections_available = FALSE;
@@ -4513,14 +3975,13 @@ static CURLcode create_conn(struct Curl_easy *data,
goto out;
}
else {
- /* Mark the connection as used, before we add it */
- conn->inuse = TRUE;
-
/*
* This is a brand new connection, so let's store it in the connection
* cache of ours!
*/
- Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ if(result)
+ goto out;
}
#if defined(USE_NTLM)
@@ -4568,10 +4029,6 @@ static CURLcode create_conn(struct Curl_easy *data,
result = resolve_server(data, conn, async);
out:
-
- free(options);
- free(passwd);
- free(user);
return result;
}
@@ -4656,12 +4113,16 @@ CURLcode Curl_connect(struct Curl_easy *data,
*asyncp = FALSE; /* assume synchronous resolves by default */
+ /* init the single-transfer specific data */
+ Curl_free_request_state(data);
+ memset(&data->req, 0, sizeof(struct SingleRequest));
+ data->req.maxdownload = -1;
+
/* call the stuff that needs to be called */
result = create_conn(data, in_connect, asyncp);
if(!result) {
- /* no error */
- if((*in_connect)->send_pipe.size || (*in_connect)->recv_pipe.size)
+ if(CONN_INUSE(*in_connect))
/* pipelining */
*protocol_done = TRUE;
else if(!*asyncp) {
@@ -4676,12 +4137,11 @@ CURLcode Curl_connect(struct Curl_easy *data,
*in_connect = NULL;
return result;
}
-
- if(result && *in_connect) {
- /* We're not allowed to return failure with memory left allocated
- in the connectdata struct, free those here */
- Curl_disconnect(*in_connect, FALSE); /* close the connection */
- *in_connect = NULL; /* return a NULL */
+ else if(result && *in_connect) {
+ /* We're not allowed to return failure with memory left allocated in the
+ connectdata struct, free those here */
+ Curl_disconnect(data, *in_connect, TRUE);
+ *in_connect = NULL; /* return a NULL */
}
return result;
@@ -4701,16 +4161,18 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
{
struct SingleRequest *k = &data->req;
- conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
- use */
+ if(conn) {
+ conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
+ use */
+ /* if the protocol used doesn't support wildcards, switch it off */
+ if(data->state.wildcardmatch &&
+ !(conn->handler->flags & PROTOPT_WILDCARD))
+ data->state.wildcardmatch = FALSE;
+ }
data->state.done = FALSE; /* *_done() is not called yet */
data->state.expect100header = FALSE;
- /* if the protocol used doesn't support wildcards, switch it off */
- if(data->state.wildcardmatch &&
- !(conn->handler->flags & PROTOPT_WILDCARD))
- data->state.wildcardmatch = FALSE;
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
@@ -4850,3 +4312,34 @@ static unsigned int get_protocol_family(unsigned int protocol)
return family;
}
+
+
+/*
+ * Wrapper to call functions in Curl_conncache_foreach()
+ *
+ * Returns always 0.
+ */
+static int conn_upkeep(struct connectdata *conn,
+ void *param)
+{
+ /* Param is unused. */
+ (void)param;
+
+ if(conn->handler->connection_check) {
+ /* Do a protocol-specific keepalive check on the connection. */
+ conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
+ }
+
+ return 0; /* continue iteration */
+}
+
+CURLcode Curl_upkeep(struct conncache *conn_cache,
+ void *data)
+{
+ /* Loop over every connection and make connection alive. */
+ Curl_conncache_foreach(data,
+ conn_cache,
+ data,
+ conn_upkeep);
+ return CURLE_OK;
+}
diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h
index a70bd5466..095d63833 100644
--- a/Utilities/cmcurl/lib/url.h
+++ b/Utilities/cmcurl/lib/url.h
@@ -27,6 +27,18 @@
#define READBUFFER_MAX CURL_MAX_READ_SIZE
#define READBUFFER_MIN 1024
+/* The default upload buffer size, should not be smaller than
+ CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
+ a write callback.
+
+ The size was 16KB for many years but was bumped to 64KB because it makes
+ libcurl able to do significantly faster uploads in some circumstances. Even
+ larger buffers can help further, but this is deemed a fair memory/speed
+ compromise. */
+#define UPLOADBUFFER_DEFAULT 65536
+#define UPLOADBUFFER_MAX (2*1024*1024)
+#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
+
/*
* Prototypes for library-wide functions provided by url.c
*/
@@ -34,12 +46,16 @@
CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_open(struct Curl_easy **curl);
CURLcode Curl_init_userdefined(struct Curl_easy *data);
-CURLcode Curl_dupset(struct Curl_easy * dst, struct Curl_easy * src);
+
void Curl_freeset(struct Curl_easy * data);
+/* free the URL pieces */
+void Curl_up_free(struct Curl_easy *data);
+CURLcode Curl_uc_to_curlcode(CURLUcode uc);
CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, struct connectdata **,
bool *async, bool *protocol_connect);
-CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
+CURLcode Curl_disconnect(struct Curl_easy *data,
+ struct connectdata *, bool dead_connection);
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
@@ -56,9 +72,7 @@ int Curl_doing_getsock(struct connectdata *conn,
CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
-bool Curl_isPipeliningEnabled(const struct Curl_easy *handle);
-CURLcode Curl_addHandleToPipeline(struct Curl_easy *handle,
- struct curl_llist *pipeline);
+
int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline);
/* remove the specified connection from all (possible) pipelines and related
@@ -66,7 +80,9 @@ int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
void Curl_getoff_all_pipelines(struct Curl_easy *data,
struct connectdata *conn);
-void Curl_close_connections(struct Curl_easy *data);
+CURLcode Curl_upkeep(struct conncache *conn_cache, void *data);
+
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
diff --git a/Utilities/cmcurl/lib/urlapi-int.h b/Utilities/cmcurl/lib/urlapi-int.h
new file mode 100644
index 000000000..a57d2e22b
--- /dev/null
+++ b/Utilities/cmcurl/lib/urlapi-int.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_URLAPI_INT_H
+#define HEADER_CURL_URLAPI_INT_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"
+/* scheme is not URL encoded, the longest libcurl supported ones are 6
+ letters */
+#define MAX_SCHEME_LEN 8
+
+bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
+char *Curl_concat_url(const char *base, const char *relurl);
+size_t Curl_strlen_url(const char *url, bool relative);
+void Curl_strcpy_url(char *output, const char *url, bool relative);
+#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
new file mode 100644
index 000000000..c53e52343
--- /dev/null
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -0,0 +1,1340 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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"
+#include "urlapi-int.h"
+#include "strcase.h"
+#include "dotdot.h"
+#include "url.h"
+#include "escape.h"
+#include "curl_ctype.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+ /* MSDOS/Windows style drive prefix, eg c: in c:foo */
+#define STARTS_WITH_DRIVE_PREFIX(str) \
+ ((('a' <= str[0] && str[0] <= 'z') || \
+ ('A' <= str[0] && str[0] <= 'Z')) && \
+ (str[1] == ':'))
+
+ /* MSDOS/Windows style drive prefix, optionally with
+ * a '|' instead of ':', followed by a slash or NUL */
+#define STARTS_WITH_URL_DRIVE_PREFIX(str) \
+ ((('a' <= (str)[0] && (str)[0] <= 'z') || \
+ ('A' <= (str)[0] && (str)[0] <= 'Z')) && \
+ ((str)[1] == ':' || (str)[1] == '|') && \
+ ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0))
+
+/* Internal representation of CURLU. Point to URL-encoded strings. */
+struct Curl_URL {
+ char *scheme;
+ char *user;
+ char *password;
+ char *options; /* IMAP only? */
+ char *host;
+ char *port;
+ char *path;
+ char *query;
+ char *fragment;
+
+ char *scratch; /* temporary scratch area */
+ long portnum; /* the numerical version */
+};
+
+#define DEFAULT_SCHEME "https"
+
+static void free_urlhandle(struct Curl_URL *u)
+{
+ free(u->scheme);
+ free(u->user);
+ free(u->password);
+ free(u->options);
+ free(u->host);
+ free(u->port);
+ free(u->path);
+ free(u->query);
+ free(u->fragment);
+ free(u->scratch);
+}
+
+/* move the full contents of one handle onto another and
+ free the original */
+static void mv_urlhandle(struct Curl_URL *from,
+ struct Curl_URL *to)
+{
+ free_urlhandle(to);
+ *to = *from;
+ free(from);
+}
+
+/*
+ * Find the separator at the end of the host name, or the '?' in cases like
+ * http://www.url.com?id=2380
+ */
+static const char *find_host_sep(const char *url)
+{
+ const char *sep;
+ const char *query;
+
+ /* Find the start of the hostname */
+ sep = strstr(url, "//");
+ if(!sep)
+ sep = url;
+ else
+ sep += 2;
+
+ query = strchr(sep, '?');
+ sep = strchr(sep, '/');
+
+ if(!sep)
+ sep = url + strlen(url);
+
+ if(!query)
+ query = url + strlen(url);
+
+ return sep < query ? sep : query;
+}
+
+/*
+ * 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
+ * will fail.
+ */
+size_t Curl_strlen_url(const char *url, bool relative)
+{
+ const unsigned char *ptr;
+ size_t newlen = 0;
+ bool left = TRUE; /* left side of the ? */
+ const unsigned char *host_sep = (const unsigned char *) url;
+
+ if(!relative)
+ host_sep = (const unsigned char *) find_host_sep(url);
+
+ for(ptr = (unsigned char *)url; *ptr; ptr++) {
+
+ if(ptr < host_sep) {
+ ++newlen;
+ continue;
+ }
+
+ switch(*ptr) {
+ case '?':
+ left = FALSE;
+ /* FALLTHROUGH */
+ default:
+ if(urlchar_needs_escaping(*ptr))
+ newlen += 2;
+ newlen++;
+ break;
+ case ' ':
+ if(left)
+ newlen += 3;
+ else
+ newlen++;
+ break;
+ }
+ }
+ return newlen;
+}
+
+/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
+ * the source URL accordingly.
+ * URL encoding should be skipped for host names, otherwise IDN resolution
+ * will fail.
+ */
+void Curl_strcpy_url(char *output, const char *url, bool relative)
+{
+ /* we must add this with whitespace-replacing */
+ bool left = TRUE;
+ const unsigned char *iptr;
+ char *optr = output;
+ const unsigned char *host_sep = (const unsigned char *) url;
+
+ if(!relative)
+ host_sep = (const unsigned char *) find_host_sep(url);
+
+ for(iptr = (unsigned char *)url; /* read from here */
+ *iptr; /* until zero byte */
+ iptr++) {
+
+ if(iptr < host_sep) {
+ *optr++ = *iptr;
+ continue;
+ }
+
+ switch(*iptr) {
+ case '?':
+ left = FALSE;
+ /* FALLTHROUGH */
+ default:
+ if(urlchar_needs_escaping(*iptr)) {
+ snprintf(optr, 4, "%%%02x", *iptr);
+ optr += 3;
+ }
+ else
+ *optr++=*iptr;
+ break;
+ case ' ':
+ if(left) {
+ *optr++='%'; /* add a '%' */
+ *optr++='2'; /* add a '2' */
+ *optr++='0'; /* add a '0' */
+ }
+ else
+ *optr++='+'; /* add a '+' here */
+ break;
+ }
+ }
+ *optr = 0; /* zero terminate output buffer */
+
+}
+
+/*
+ * Returns true if the given URL is absolute (as opposed to relative) within
+ * the buffer size. Returns the scheme in the buffer if TRUE and 'buf' is
+ * non-NULL.
+ */
+bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
+{
+ size_t i;
+#ifdef WIN32
+ if(STARTS_WITH_DRIVE_PREFIX(url))
+ return FALSE;
+#endif
+ for(i = 0; i < buflen && url[i]; ++i) {
+ char s = url[i];
+ if(s == ':') {
+ if(buf)
+ buf[i] = 0;
+ return TRUE;
+ }
+ /* RFC 3986 3.1 explains:
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+ else if(ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') ) {
+ if(buf)
+ buf[i] = (char)TOLOWER(s);
+ }
+ else
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * Concatenate a relative URL to a base URL making it absolute.
+ * URL-encodes any spaces.
+ * The returned pointer must be freed by the caller unless NULL
+ * (returns NULL on out of memory).
+ */
+char *Curl_concat_url(const char *base, const char *relurl)
+{
+ /***
+ TRY to append this new path to the old URL
+ to the right of the host part. Oh crap, this is doomed to cause
+ problems in the future...
+ */
+ char *newest;
+ char *protsep;
+ char *pathsep;
+ size_t newlen;
+ bool host_changed = FALSE;
+
+ const char *useurl = relurl;
+ size_t urllen;
+
+ /* we must make our own copy of the URL to play with, as it may
+ point to read-only data */
+ char *url_clone = strdup(base);
+
+ if(!url_clone)
+ return NULL; /* skip out of this NOW */
+
+ /* protsep points to the start of the host name */
+ protsep = strstr(url_clone, "//");
+ if(!protsep)
+ protsep = url_clone;
+ else
+ protsep += 2; /* pass the slashes */
+
+ if('/' != relurl[0]) {
+ int level = 0;
+
+ /* First we need to find out if there's a ?-letter in the URL,
+ and cut it and the right-side of that off */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep = 0;
+
+ /* we have a relative path to append to the last slash if there's one
+ available, or if the new URL is just a query string (starts with a
+ '?') we append the new one at the end of the entire currently worked
+ out URL */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep = 0;
+ }
+
+ /* Check if there's any slash after the host name, and if so, remember
+ that position instead */
+ pathsep = strchr(protsep, '/');
+ if(pathsep)
+ protsep = pathsep + 1;
+ else
+ protsep = NULL;
+
+ /* now deal with one "./" or any amount of "../" in the newurl
+ and act accordingly */
+
+ if((useurl[0] == '.') && (useurl[1] == '/'))
+ useurl += 2; /* just skip the "./" */
+
+ while((useurl[0] == '.') &&
+ (useurl[1] == '.') &&
+ (useurl[2] == '/')) {
+ level++;
+ useurl += 3; /* pass the "../" */
+ }
+
+ if(protsep) {
+ while(level--) {
+ /* cut off one more level from the right of the original URL */
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep = 0;
+ else {
+ *protsep = 0;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* We got a new absolute path for this server */
+
+ if((relurl[0] == '/') && (relurl[1] == '/')) {
+ /* the new URL starts with //, just keep the protocol part from the
+ original one */
+ *protsep = 0;
+ useurl = &relurl[2]; /* we keep the slashes from the original, so we
+ skip the new ones */
+ host_changed = TRUE;
+ }
+ else {
+ /* cut off the original URL from the first slash, or deal with URLs
+ without slash */
+ pathsep = strchr(protsep, '/');
+ if(pathsep) {
+ /* When people use badly formatted URLs, such as
+ "http://www.url.com?dir=/home/daniel" we must not use the first
+ slash, if there's a ?-letter before it! */
+ char *sep = strchr(protsep, '?');
+ if(sep && (sep < pathsep))
+ pathsep = sep;
+ *pathsep = 0;
+ }
+ else {
+ /* There was no slash. Now, since we might be operating on a badly
+ formatted URL, such as "http://www.url.com?id=2380" which doesn't
+ use a slash separator as it is supposed to, we need to check for a
+ ?-letter as well! */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep = 0;
+ }
+ }
+ }
+
+ /* If the new part contains a space, this is a mighty stupid redirect
+ but we still make an effort to do "right". To the left of a '?'
+ letter we replace each space with %20 while it is replaced with '+'
+ on the right side of the '?' letter.
+ */
+ newlen = Curl_strlen_url(useurl, !host_changed);
+
+ urllen = strlen(url_clone);
+
+ newest = malloc(urllen + 1 + /* possible slash */
+ newlen + 1 /* zero byte */);
+
+ if(!newest) {
+ free(url_clone); /* don't leak this */
+ return NULL;
+ }
+
+ /* copy over the root url part */
+ memcpy(newest, url_clone, urllen);
+
+ /* check if we need to append a slash */
+ if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
+ ;
+ else
+ newest[urllen++]='/';
+
+ /* then append the new piece on the right side */
+ Curl_strcpy_url(&newest[urllen], useurl, !host_changed);
+
+ free(url_clone);
+
+ return newest;
+}
+
+/*
+ * parse_hostname_login()
+ *
+ * Parse the login details (user name, password and options) from the URL and
+ * strip them out of the host name
+ *
+ */
+static CURLUcode parse_hostname_login(struct Curl_URL *u,
+ const struct Curl_handler *h,
+ char **hostname,
+ unsigned int flags)
+{
+ CURLUcode result = CURLUE_OK;
+ CURLcode ccode;
+ char *userp = NULL;
+ char *passwdp = NULL;
+ char *optionsp = NULL;
+
+ /* At this point, we're hoping all the other special cases have
+ * been taken care of, so conn->host.name is at most
+ * [user[:password][;options]]@]hostname
+ *
+ * We need somewhere to put the embedded details, so do that first.
+ */
+
+ char *ptr = strchr(*hostname, '@');
+ char *login = *hostname;
+
+ if(!ptr)
+ goto out;
+
+ /* We will now try to extract the
+ * possible login information in a string like:
+ * ftp://user:password@ftp.my.site:8021/README */
+ *hostname = ++ptr;
+
+ /* We could use the login information in the URL so extract it. Only parse
+ options if the handler says we should. Note that 'h' might be NULL! */
+ ccode = Curl_parse_login_details(login, ptr - login - 1,
+ &userp, &passwdp,
+ (h && (h->flags & PROTOPT_URLOPTIONS)) ?
+ &optionsp:NULL);
+ if(ccode) {
+ result = CURLUE_MALFORMED_INPUT;
+ goto out;
+ }
+
+ if(userp) {
+ if(flags & CURLU_DISALLOW_USER) {
+ /* Option DISALLOW_USER is set and url contains username. */
+ result = CURLUE_USER_NOT_ALLOWED;
+ goto out;
+ }
+
+ u->user = userp;
+ }
+
+ if(passwdp)
+ u->password = passwdp;
+
+ if(optionsp)
+ u->options = optionsp;
+
+ return CURLUE_OK;
+ out:
+
+ free(userp);
+ free(passwdp);
+ free(optionsp);
+
+ return result;
+}
+
+static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
+{
+ char *portptr;
+ char endbracket;
+ int len;
+
+ if((1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.%%]%c%n",
+ &endbracket, &len)) &&
+ (']' == endbracket)) {
+ /* this is a RFC2732-style specified IP-address */
+ portptr = &hostname[len];
+ if (*portptr != ':')
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else
+ portptr = strchr(hostname, ':');
+
+ if(portptr) {
+ char *rest;
+ long port;
+ char portbuf[7];
+
+ if(!ISDIGIT(portptr[1]))
+ return CURLUE_BAD_PORT_NUMBER;
+
+ port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
+
+ if((port <= 0) || (port > 0xffff))
+ /* Single unix standard says port numbers are 16 bits long, but we don't
+ treat port zero as OK. */
+ return CURLUE_BAD_PORT_NUMBER;
+
+ if(rest[0])
+ return CURLUE_BAD_PORT_NUMBER;
+
+ if(rest != &portptr[1]) {
+ *portptr++ = '\0'; /* cut off the name there */
+ *rest = 0;
+ /* generate a new to get rid of leading zeroes etc */
+ snprintf(portbuf, sizeof(portbuf), "%ld", port);
+ u->portnum = port;
+ u->port = strdup(portbuf);
+ if(!u->port)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ else {
+ /* Browser behavior adaptation. If there's a colon with no digits after,
+ just cut off the name there which makes us ignore the colon and just
+ use the default port. Firefox and Chrome both do that. */
+ *portptr = '\0';
+ }
+ }
+
+ return CURLUE_OK;
+}
+
+/* scan for byte values < 31 or 127 */
+static CURLUcode junkscan(char *part)
+{
+ char badbytes[]={
+ /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x7f,
+ 0x00 /* zero terminate */
+ };
+ if(part) {
+ size_t n = strlen(part);
+ size_t nfine = strcspn(part, badbytes);
+ if(nfine != n)
+ /* since we don't know which part is scanned, return a generic error
+ code */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ return CURLUE_OK;
+}
+
+static CURLUcode hostname_check(char *hostname, unsigned int flags)
+{
+ const char *l = NULL; /* accepted characters */
+ size_t len;
+ size_t hlen = strlen(hostname);
+ (void)flags;
+
+ if(hostname[0] == '[') {
+ hostname++;
+ l = "0123456789abcdefABCDEF::.%";
+ hlen -= 2;
+ }
+
+ if(l) {
+ /* only valid letters are ok */
+ len = strspn(hostname, l);
+ if(hlen != len)
+ /* hostname with bad content */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else {
+ /* letters from the second string is not ok */
+ len = strcspn(hostname, " ");
+ if(hlen != len)
+ /* hostname with bad content */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ return CURLUE_OK;
+}
+
+#define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#'))
+
+static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
+{
+ char *path;
+ bool path_alloced = FALSE;
+ char *hostname;
+ char *query = NULL;
+ char *fragment = NULL;
+ CURLUcode result;
+ bool url_has_scheme = FALSE;
+ char schemebuf[MAX_SCHEME_LEN];
+ char *schemep = NULL;
+ size_t schemelen = 0;
+ size_t urllen;
+ const struct Curl_handler *h = NULL;
+
+ if(!url)
+ return CURLUE_MALFORMED_INPUT;
+
+ /*************************************************************
+ * Parse the URL.
+ ************************************************************/
+ /* allocate scratch area */
+ urllen = strlen(url);
+ path = u->scratch = malloc(urllen * 2 + 2);
+ if(!path)
+ return CURLUE_OUT_OF_MEMORY;
+
+ hostname = &path[urllen + 1];
+ hostname[0] = 0;
+
+ if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) {
+ url_has_scheme = TRUE;
+ schemelen = strlen(schemebuf);
+ }
+
+ /* handle the file: scheme */
+ if(url_has_scheme && strcasecompare(schemebuf, "file")) {
+ /* path has been allocated large enough to hold this */
+ strcpy(path, &url[5]);
+
+ hostname = NULL; /* no host for file: URLs */
+ u->scheme = strdup("file");
+ if(!u->scheme)
+ return CURLUE_OUT_OF_MEMORY;
+
+ /* Extra handling URLs with an authority component (i.e. that start with
+ * "file://")
+ *
+ * We allow omitted hostname (e.g. file:/<path>) -- valid according to
+ * RFC 8089, but not the (current) WHAT-WG URL spec.
+ */
+ if(path[0] == '/' && path[1] == '/') {
+ /* swallow the two slashes */
+ char *ptr = &path[2];
+
+ /*
+ * According to RFC 8089, a file: URL can be reliably dereferenced if:
+ *
+ * o it has no/blank hostname, or
+ *
+ * o the hostname matches "localhost" (case-insensitively), or
+ *
+ * o the hostname is a FQDN that resolves to this machine.
+ *
+ * For brevity, we only consider URLs with empty, "localhost", or
+ * "127.0.0.1" hostnames as local.
+ *
+ * Additionally, there is an exception for URLs with a Windows drive
+ * letter in the authority (which was accidentally omitted from RFC 8089
+ * Appendix E, but believe me, it was meant to be there. --MK)
+ */
+ if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) {
+ /* the URL includes a host name, it must match "localhost" or
+ "127.0.0.1" to be valid */
+ if(!checkprefix("localhost/", ptr) &&
+ !checkprefix("127.0.0.1/", ptr)) {
+ /* Invalid file://hostname/, expected localhost or 127.0.0.1 or
+ none */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ ptr += 9; /* now points to the slash after the host */
+ }
+
+ path = ptr;
+ }
+
+#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
+ /* Don't allow Windows drive letters when not in Windows.
+ * This catches both "file:/c:" and "file:c:" */
+ if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
+ STARTS_WITH_URL_DRIVE_PREFIX(path)) {
+ /* File drive letters are only accepted in MSDOS/Windows */
+ return CURLUE_MALFORMED_INPUT;
+ }
+#else
+ /* If the path starts with a slash and a drive letter, ditch the slash */
+ if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
+ /* This cannot be done with strcpy, as the memory chunks overlap! */
+ memmove(path, &path[1], strlen(&path[1]) + 1);
+ }
+#endif
+
+ }
+ else {
+ /* clear path */
+ const char *p;
+ const char *hostp;
+ size_t len;
+ path[0] = 0;
+
+ if(url_has_scheme) {
+ int i = 0;
+ p = &url[schemelen + 1];
+ while(p && (*p == '/') && (i < 4)) {
+ p++;
+ i++;
+ }
+ if((i < 1) || (i>3))
+ /* less than one or more than three slashes */
+ return CURLUE_MALFORMED_INPUT;
+
+ schemep = schemebuf;
+ if(!Curl_builtin_scheme(schemep) &&
+ !(flags & CURLU_NON_SUPPORT_SCHEME))
+ return CURLUE_UNSUPPORTED_SCHEME;
+
+ if(junkscan(schemep))
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else {
+ /* no scheme! */
+
+ if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
+ return CURLUE_MALFORMED_INPUT;
+ if(flags & CURLU_DEFAULT_SCHEME)
+ schemep = (char *) DEFAULT_SCHEME;
+
+ /*
+ * The URL was badly formatted, let's try without scheme specified.
+ */
+ p = url;
+ }
+ hostp = p; /* host name starts here */
+
+ while(*p && !HOSTNAME_END(*p)) /* find end of host name */
+ p++;
+
+ len = p - hostp;
+ if(!len)
+ return CURLUE_MALFORMED_INPUT;
+
+ memcpy(hostname, hostp, len);
+ hostname[len] = 0;
+
+ if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+ /* legacy curl-style guess based on host name */
+ if(checkprefix("ftp.", hostname))
+ schemep = (char *)"ftp";
+ else if(checkprefix("dict.", hostname))
+ schemep = (char *)"dict";
+ else if(checkprefix("ldap.", hostname))
+ schemep = (char *)"ldap";
+ else if(checkprefix("imap.", hostname))
+ schemep = (char *)"imap";
+ else if(checkprefix("smtp.", hostname))
+ schemep = (char *)"smtp";
+ else if(checkprefix("pop3.", hostname))
+ schemep = (char *)"pop3";
+ else
+ schemep = (char *)"http";
+ }
+
+ len = strlen(p);
+ memcpy(path, p, len);
+ path[len] = 0;
+
+ u->scheme = strdup(schemep);
+ if(!u->scheme)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ /* if this is a known scheme, get some details */
+ h = Curl_builtin_scheme(u->scheme);
+
+ if(junkscan(path))
+ return CURLUE_MALFORMED_INPUT;
+
+ query = strchr(path, '?');
+ if(query)
+ *query++ = 0;
+
+ fragment = strchr(query?query:path, '#');
+ if(fragment)
+ *fragment++ = 0;
+
+ if(!path[0])
+ /* if there's no path set, unset */
+ path = NULL;
+ else if(!(flags & CURLU_PATH_AS_IS)) {
+ /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
+ char *newp = Curl_dedotdotify(path);
+ if(!newp)
+ return CURLUE_OUT_OF_MEMORY;
+
+ if(strcmp(newp, path)) {
+ /* if we got a new version */
+ path = newp;
+ path_alloced = TRUE;
+ }
+ else
+ free(newp);
+ }
+ if(path) {
+ u->path = path_alloced?path:strdup(path);
+ if(!u->path)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ if(hostname) {
+ /*
+ * Parse the login details and strip them out of the host name.
+ */
+ if(junkscan(hostname))
+ return CURLUE_MALFORMED_INPUT;
+
+ result = parse_hostname_login(u, h, &hostname, flags);
+ if(result)
+ return result;
+
+ result = parse_port(u, hostname);
+ if(result)
+ return result;
+
+ result = hostname_check(hostname, flags);
+ if(result)
+ return result;
+
+ u->host = strdup(hostname);
+ if(!u->host)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ if(query && query[0]) {
+ u->query = strdup(query);
+ if(!u->query)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ if(fragment && fragment[0]) {
+ u->fragment = strdup(fragment);
+ if(!u->fragment)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ free(u->scratch);
+ u->scratch = NULL;
+
+ return CURLUE_OK;
+}
+
+/*
+ * Parse the URL and set the relevant members of the Curl_URL struct.
+ */
+static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
+{
+ CURLUcode result = seturl(url, u, flags);
+ if(result) {
+ free_urlhandle(u);
+ memset(u, 0, sizeof(struct Curl_URL));
+ }
+ return result;
+}
+
+/*
+ */
+CURLU *curl_url(void)
+{
+ return calloc(sizeof(struct Curl_URL), 1);
+}
+
+void curl_url_cleanup(CURLU *u)
+{
+ if(u) {
+ free_urlhandle(u);
+ free(u);
+ }
+}
+
+#define DUP(dest, src, name) \
+ if(src->name) { \
+ dest->name = strdup(src->name); \
+ if(!dest->name) \
+ goto fail; \
+ }
+
+CURLU *curl_url_dup(CURLU *in)
+{
+ struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
+ if(u) {
+ DUP(u, in, scheme);
+ DUP(u, in, user);
+ DUP(u, in, password);
+ DUP(u, in, options);
+ DUP(u, in, host);
+ DUP(u, in, port);
+ DUP(u, in, path);
+ DUP(u, in, query);
+ DUP(u, in, fragment);
+ u->portnum = in->portnum;
+ }
+ return u;
+ fail:
+ curl_url_cleanup(u);
+ return NULL;
+}
+
+CURLUcode curl_url_get(CURLU *u, CURLUPart what,
+ char **part, unsigned int flags)
+{
+ char *ptr;
+ CURLUcode ifmissing = CURLUE_UNKNOWN_PART;
+ char portbuf[7];
+ bool urldecode = (flags & CURLU_URLDECODE)?1:0;
+ bool plusdecode = FALSE;
+ (void)flags;
+ if(!u)
+ return CURLUE_BAD_HANDLE;
+ if(!part)
+ return CURLUE_BAD_PARTPOINTER;
+ *part = NULL;
+
+ switch(what) {
+ case CURLUPART_SCHEME:
+ ptr = u->scheme;
+ ifmissing = CURLUE_NO_SCHEME;
+ urldecode = FALSE; /* never for schemes */
+ break;
+ case CURLUPART_USER:
+ ptr = u->user;
+ ifmissing = CURLUE_NO_USER;
+ break;
+ case CURLUPART_PASSWORD:
+ ptr = u->password;
+ ifmissing = CURLUE_NO_PASSWORD;
+ break;
+ case CURLUPART_OPTIONS:
+ ptr = u->options;
+ ifmissing = CURLUE_NO_OPTIONS;
+ break;
+ case CURLUPART_HOST:
+ ptr = u->host;
+ ifmissing = CURLUE_NO_HOST;
+ break;
+ case CURLUPART_PORT:
+ ptr = u->port;
+ ifmissing = CURLUE_NO_PORT;
+ urldecode = FALSE; /* never for port */
+ if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) {
+ /* there's no stored port number, but asked to deliver
+ a default one for the scheme */
+ const struct Curl_handler *h =
+ Curl_builtin_scheme(u->scheme);
+ if(h) {
+ snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ ptr = portbuf;
+ }
+ }
+ else if(ptr && u->scheme) {
+ /* there is a stored port number, but ask to inhibit if
+ it matches the default one for the scheme */
+ const struct Curl_handler *h =
+ Curl_builtin_scheme(u->scheme);
+ if(h && (h->defport == u->portnum) &&
+ (flags & CURLU_NO_DEFAULT_PORT))
+ ptr = NULL;
+ }
+ break;
+ case CURLUPART_PATH:
+ ptr = u->path;
+ if(!ptr) {
+ ptr = u->path = strdup("/");
+ if(!u->path)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ break;
+ case CURLUPART_QUERY:
+ ptr = u->query;
+ ifmissing = CURLUE_NO_QUERY;
+ plusdecode = urldecode;
+ break;
+ case CURLUPART_FRAGMENT:
+ ptr = u->fragment;
+ ifmissing = CURLUE_NO_FRAGMENT;
+ break;
+ case CURLUPART_URL: {
+ char *url;
+ char *scheme;
+ char *options = u->options;
+ char *port = u->port;
+ if(u->scheme && strcasecompare("file", u->scheme)) {
+ url = aprintf("file://%s%s%s",
+ u->path,
+ u->fragment? "#": "",
+ u->fragment? u->fragment : "");
+ }
+ else if(!u->host)
+ return CURLUE_NO_HOST;
+ else {
+ const struct Curl_handler *h = NULL;
+ if(u->scheme)
+ scheme = u->scheme;
+ else if(flags & CURLU_DEFAULT_SCHEME)
+ scheme = (char *) DEFAULT_SCHEME;
+ else
+ return CURLUE_NO_SCHEME;
+
+ if(scheme) {
+ h = Curl_builtin_scheme(scheme);
+ if(!port && (flags & CURLU_DEFAULT_PORT)) {
+ /* there's no stored port number, but asked to deliver
+ a default one for the scheme */
+ if(h) {
+ snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ port = portbuf;
+ }
+ }
+ else if(port) {
+ /* there is a stored port number, but asked to inhibit if it matches
+ the default one for the scheme */
+ if(h && (h->defport == u->portnum) &&
+ (flags & CURLU_NO_DEFAULT_PORT))
+ port = NULL;
+ }
+ }
+ if(h && !(h->flags & PROTOPT_URLOPTIONS))
+ options = NULL;
+
+ url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ scheme,
+ u->user ? u->user : "",
+ u->password ? ":": "",
+ u->password ? u->password : "",
+ options ? ";" : "",
+ options ? options : "",
+ (u->user || u->password || options) ? "@": "",
+ u->host,
+ port ? ":": "",
+ port ? port : "",
+ (u->path && (u->path[0] != '/')) ? "/": "",
+ u->path ? u->path : "/",
+ u->query? "?": "",
+ u->query? u->query : "",
+ u->fragment? "#": "",
+ u->fragment? u->fragment : "");
+ }
+ if(!url)
+ return CURLUE_OUT_OF_MEMORY;
+ *part = url;
+ return CURLUE_OK;
+ break;
+ }
+ default:
+ ptr = NULL;
+ }
+ if(ptr) {
+ *part = strdup(ptr);
+ if(!*part)
+ return CURLUE_OUT_OF_MEMORY;
+ if(plusdecode) {
+ /* convert + to space */
+ char *plus;
+ for(plus = *part; *plus; ++plus) {
+ if(*plus == '+')
+ *plus = ' ';
+ }
+ }
+ if(urldecode) {
+ char *decoded;
+ size_t dlen;
+ CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE);
+ free(*part);
+ if(res) {
+ *part = NULL;
+ return CURLUE_URLDECODE;
+ }
+ *part = decoded;
+ }
+ return CURLUE_OK;
+ }
+ else
+ return ifmissing;
+}
+
+CURLUcode curl_url_set(CURLU *u, CURLUPart what,
+ const char *part, unsigned int flags)
+{
+ char **storep = NULL;
+ long port = 0;
+ bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0;
+ bool plusencode = FALSE;
+ bool urlskipslash = FALSE;
+ bool appendquery = FALSE;
+
+ if(!u)
+ return CURLUE_BAD_HANDLE;
+ if(!part) {
+ /* setting a part to NULL clears it */
+ switch(what) {
+ case CURLUPART_URL:
+ break;
+ case CURLUPART_SCHEME:
+ storep = &u->scheme;
+ break;
+ case CURLUPART_USER:
+ storep = &u->user;
+ break;
+ case CURLUPART_PASSWORD:
+ storep = &u->password;
+ break;
+ case CURLUPART_OPTIONS:
+ storep = &u->options;
+ break;
+ case CURLUPART_HOST:
+ storep = &u->host;
+ break;
+ case CURLUPART_PORT:
+ storep = &u->port;
+ break;
+ case CURLUPART_PATH:
+ storep = &u->path;
+ break;
+ case CURLUPART_QUERY:
+ storep = &u->query;
+ break;
+ case CURLUPART_FRAGMENT:
+ storep = &u->fragment;
+ break;
+ default:
+ return CURLUE_UNKNOWN_PART;
+ }
+ if(storep && *storep) {
+ free(*storep);
+ *storep = NULL;
+ }
+ return CURLUE_OK;
+ }
+
+ switch(what) {
+ case CURLUPART_SCHEME:
+ if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
+ /* verify that it is a fine scheme */
+ !Curl_builtin_scheme(part))
+ return CURLUE_UNSUPPORTED_SCHEME;
+ storep = &u->scheme;
+ urlencode = FALSE; /* never */
+ break;
+ case CURLUPART_USER:
+ storep = &u->user;
+ break;
+ case CURLUPART_PASSWORD:
+ storep = &u->password;
+ break;
+ case CURLUPART_OPTIONS:
+ storep = &u->options;
+ break;
+ case CURLUPART_HOST:
+ storep = &u->host;
+ break;
+ case CURLUPART_PORT:
+ urlencode = FALSE; /* never */
+ port = strtol(part, NULL, 10); /* Port number must be decimal */
+ if((port <= 0) || (port > 0xffff))
+ return CURLUE_BAD_PORT_NUMBER;
+ storep = &u->port;
+ break;
+ case CURLUPART_PATH:
+ urlskipslash = TRUE;
+ storep = &u->path;
+ break;
+ case CURLUPART_QUERY:
+ plusencode = urlencode;
+ appendquery = (flags & CURLU_APPENDQUERY)?1:0;
+ storep = &u->query;
+ break;
+ case CURLUPART_FRAGMENT:
+ storep = &u->fragment;
+ break;
+ case CURLUPART_URL: {
+ /*
+ * Allow a new URL to replace the existing (if any) contents.
+ *
+ * If the existing contents is enough for a URL, allow a relative URL to
+ * replace it.
+ */
+ CURLUcode result;
+ char *oldurl;
+ char *redired_url;
+ CURLU *handle2;
+
+ if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN)) {
+ handle2 = curl_url();
+ if(!handle2)
+ return CURLUE_OUT_OF_MEMORY;
+ result = parseurl(part, handle2, flags);
+ if(!result)
+ mv_urlhandle(handle2, u);
+ else
+ curl_url_cleanup(handle2);
+ return result;
+ }
+ /* extract the full "old" URL to do the redirect on */
+ result = curl_url_get(u, CURLUPART_URL, &oldurl, flags);
+ if(result) {
+ /* couldn't get the old URL, just use the new! */
+ handle2 = curl_url();
+ if(!handle2)
+ return CURLUE_OUT_OF_MEMORY;
+ result = parseurl(part, handle2, flags);
+ if(!result)
+ mv_urlhandle(handle2, u);
+ else
+ curl_url_cleanup(handle2);
+ return result;
+ }
+
+ /* apply the relative part to create a new URL */
+ redired_url = Curl_concat_url(oldurl, part);
+ free(oldurl);
+ if(!redired_url)
+ return CURLUE_OUT_OF_MEMORY;
+
+ /* now parse the new URL */
+ handle2 = curl_url();
+ if(!handle2) {
+ free(redired_url);
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ result = parseurl(redired_url, handle2, flags);
+ free(redired_url);
+ if(!result)
+ mv_urlhandle(handle2, u);
+ else
+ curl_url_cleanup(handle2);
+ return result;
+ }
+ default:
+ return CURLUE_UNKNOWN_PART;
+ }
+ if(storep) {
+ const char *newp = part;
+ size_t nalloc = strlen(part);
+
+ if(urlencode) {
+ const char *i;
+ char *o;
+ bool free_part = FALSE;
+ char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
+ if(!enc)
+ return CURLUE_OUT_OF_MEMORY;
+ if(plusencode) {
+ /* space to plus */
+ i = part;
+ for(o = enc; *i; ++o, ++i)
+ *o = (*i == ' ') ? '+' : *i;
+ *o = 0; /* zero terminate */
+ part = strdup(enc);
+ if(!part) {
+ free(enc);
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ free_part = TRUE;
+ }
+ for(i = part, o = enc; *i; i++) {
+ if(Curl_isunreserved(*i) ||
+ ((*i == '/') && urlskipslash) ||
+ ((*i == '=') && appendquery) ||
+ ((*i == '+') && plusencode)) {
+ *o = *i;
+ o++;
+ }
+ else {
+ snprintf(o, 4, "%%%02x", *i);
+ o += 3;
+ }
+ }
+ *o = 0; /* zero terminate */
+ newp = enc;
+ if(free_part)
+ free((char *)part);
+ }
+ else {
+ char *p;
+ newp = strdup(part);
+ if(!newp)
+ return CURLUE_OUT_OF_MEMORY;
+ p = (char *)newp;
+ while(*p) {
+ /* make sure percent encoded are lower case */
+ if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
+ (ISUPPER(p[1]) || ISUPPER(p[2]))) {
+ p[1] = (char)TOLOWER(p[1]);
+ p[2] = (char)TOLOWER(p[2]);
+ p += 3;
+ }
+ else
+ p++;
+ }
+ }
+
+ if(appendquery) {
+ /* Append the string onto the old query. Add a '&' separator if none is
+ present at the end of the exsting query already */
+ size_t querylen = u->query ? strlen(u->query) : 0;
+ bool addamperand = querylen && (u->query[querylen -1] != '&');
+ if(querylen) {
+ size_t newplen = strlen(newp);
+ char *p = malloc(querylen + addamperand + newplen + 1);
+ if(!p) {
+ free((char *)newp);
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ strcpy(p, u->query); /* original query */
+ if(addamperand)
+ p[querylen] = '&'; /* ampersand */
+ strcpy(&p[querylen + addamperand], newp); /* new suffix */
+ free((char *)newp);
+ free(*storep);
+ *storep = p;
+ return CURLUE_OK;
+ }
+ }
+
+ free(*storep);
+ *storep = (char *)newp;
+ }
+ /* set after the string, to make it not assigned if the allocation above
+ fails */
+ if(port)
+ u->portnum = port;
+ return CURLUE_OK;
+}
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 7fae00fd9..11a6a22c6 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -80,6 +80,7 @@
#define RESP_TIMEOUT (1800*1000)
#include "cookie.h"
+#include "psl.h"
#include "formdata.h"
#ifdef HAVE_NETINET_IN_H
@@ -141,9 +142,6 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
-/* The upload buffer size, should not be smaller than CURL_MAX_WRITE_SIZE, as
- it needs to hold a full buffer as could be sent in a write callback */
-#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE
/* The "master buffer" is for HTTP pipelining */
#define MASTERBUF_SIZE 16384
@@ -156,11 +154,6 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
-/* Some convenience macros to get the larger/smaller value out of two given.
- We prefix with CURL to prevent name collisions. */
-#define CURLMAX(x,y) ((x)>(y)?(x):(y))
-#define CURLMIN(x,y) ((x)<(y)?(x):(y))
-
#ifdef HAVE_GSSAPI
/* Types needed for krb5-ftp connections */
struct krb5buffer {
@@ -226,6 +219,7 @@ struct ssl_primary_config {
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */
+ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
};
struct ssl_config_data {
@@ -474,7 +468,6 @@ struct hostname {
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
-#ifdef CURLRES_ASYNCH
struct Curl_async {
char *hostname;
int port;
@@ -483,7 +476,6 @@ struct Curl_async {
int status; /* if done is TRUE, this is the status from the callback */
void *os_specific; /* 'struct thread_data' for Windows */
};
-#endif
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
@@ -509,6 +501,28 @@ enum upgrade101 {
UPGR101_WORKING /* talking upgraded protocol */
};
+struct dohresponse {
+ unsigned char *memory;
+ size_t size;
+};
+
+/* one of these for each DoH request */
+struct dnsprobe {
+ CURL *easy;
+ int dnstype;
+ unsigned char dohbuffer[512];
+ size_t dohlen;
+ struct dohresponse serverdoh;
+};
+
+struct dohdata {
+ struct curl_slist *headers;
+ struct dnsprobe probe[2];
+ unsigned int pending; /* still outstanding requests */
+ const char *host;
+ int port;
+};
+
/*
* Request specific data in the easy handle (Curl_easy). Previously,
* these members were on the connectdata struct but since a conn struct may
@@ -604,6 +618,7 @@ struct SingleRequest {
void *protop; /* Allocated protocol-specific data. Each protocol
handler makes sure this points to data it needs. */
+ struct dohdata doh; /* DoH specific data for this request */
};
/*
@@ -634,7 +649,7 @@ struct Curl_handler {
*/
CURLcode (*connect_it)(struct connectdata *, bool *done);
- /* See above. Currently only used for FTP. */
+ /* See above. */
CURLcode (*connecting)(struct connectdata *, bool *done);
CURLcode (*doing)(struct connectdata *, bool *done);
@@ -714,6 +729,7 @@ struct Curl_handler {
#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */
+#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
@@ -779,11 +795,12 @@ struct connectdata {
curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
void *closesocket_client;
- bool inuse; /* This is a marker for the connection cache logic. If this is
- TRUE this handle is being used by one or more easy handles
- and can only used by any other easy handle without careful
- consideration (== only for pipelining/multiplexing) and it
- cannot be used by another multi handle! */
+ /* This is used by the connection cache logic. If this returns TRUE, this
+ handle is being used by one or more easy handles and can only used by any
+ other easy handle without careful consideration (== only for
+ pipelining/multiplexing) and it cannot be used by another multi
+ handle! */
+#define CONN_INUSE(c) ((c)->send_pipe.size + (c)->recv_pipe.size)
/**** Fields set when inited and not modified again */
long connection_id; /* Contains a unique number to make it easier to
@@ -889,6 +906,13 @@ struct connectdata {
long ip_version; /* copied from the Curl_easy at creation time */
+ /* Protocols can use a custom keepalive mechanism to keep connections alive.
+ This allows those protocols to track the last time the keepalive mechanism
+ was used on this connection. */
+ struct curltime keepalive;
+
+ long upkeep_interval_ms; /* Time between calls for connection upkeep. */
+
/**** curl_get() phase fields */
curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
@@ -966,11 +990,8 @@ struct connectdata {
#endif
char syserr_buf [256]; /* buffer for Curl_strerror() */
-
-#ifdef CURLRES_ASYNCH
/* data used for the asynch name resolve callback */
struct Curl_async async;
-#endif
/* These three are used for chunked-encoding trailer support */
char *trailer; /* allocated buffer to store trailer in */
@@ -1203,6 +1224,18 @@ struct time_node {
expire_id eid;
};
+/* individual pieces of the URL */
+struct urlpieces {
+ char *scheme;
+ char *hostname;
+ char *port;
+ char *user;
+ char *password;
+ char *options;
+ char *path;
+ char *query;
+};
+
struct UrlState {
/* Points to the connection cache */
@@ -1222,7 +1255,7 @@ struct UrlState {
size_t headersize; /* size of the allocation */
char *buffer; /* download buffer */
- char uploadbuffer[UPLOAD_BUFSIZE + 1]; /* upload buffer */
+ char *ulbuf; /* allocated upload buffer or NULL */
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
@@ -1265,7 +1298,7 @@ struct UrlState {
void *resolver; /* resolver state, if it is used in the URL state -
ares_channel f.e. */
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
void *engine;
#endif /* USE_OPENSSL */
@@ -1284,9 +1317,6 @@ struct UrlState {
involved in this request */
bool expect100header; /* TRUE if we added Expect: 100-continue */
- bool pipe_broke; /* TRUE if the connection we were pipelined on broke
- and we need to restart from the beginning */
-
#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
!defined(__SYMBIAN32__)
/* do FTP line-end conversions on most platforms */
@@ -1296,9 +1326,6 @@ struct UrlState {
/* for FTP downloads: how many CRLFs did we converted to LFs? */
curl_off_t crlf_conversions;
#endif
- char *pathbuffer;/* allocated buffer to store the URL's path part in */
- char *path; /* path to use, points to somewhere within the pathbuffer
- area */
bool slash_removed; /* set TRUE if the 'path' points to a path where the
initial URL slash separator has been taken off */
bool use_range;
@@ -1332,6 +1359,8 @@ struct UrlState {
#ifdef CURLDEBUG
bool conncache_lock;
#endif
+ CURLU *uh; /* URL handle for the current parsed URL */
+ struct urlpieces up;
};
@@ -1346,7 +1375,7 @@ struct DynamicStatic {
char *url; /* work URL, copied from UserDefined */
bool url_alloc; /* URL string is malloc()'ed */
char *referer; /* referer string */
- bool referer_alloc; /* referer sting is malloc()ed */
+ bool referer_alloc; /* referer string is malloc()ed */
struct curl_slist *cookielist; /* list of cookie files set by
curl_easy_setopt(COOKIEFILE) calls */
struct curl_slist *resolve; /* set to point to the set.resolve list when
@@ -1400,6 +1429,8 @@ enum dupstring {
STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */
STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
+ STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */
+ STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
STRING_USERAGENT, /* User-Agent string */
@@ -1407,6 +1438,7 @@ enum dupstring {
STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
+ STRING_SSL_ENGINE, /* name of ssl engine */
STRING_USERNAME, /* <username>, if used */
STRING_PASSWORD, /* <password>, if used */
STRING_OPTIONS, /* <options>, if used */
@@ -1439,18 +1471,23 @@ enum dupstring {
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
#endif
STRING_TARGET, /* CURLOPT_REQUEST_TARGET */
+ STRING_DOH, /* CURLOPT_DOH_URL */
/* -- end of zero-terminated strings -- */
STRING_LASTZEROTERMINATED,
- /* -- below this are pointers to binary data that cannot be strdup'ed.
- Each such pointer must be added manually to Curl_dupset() --- */
+ /* -- below this are pointers to binary data that cannot be strdup'ed. --- */
STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
STRING_LAST /* not used, just an end-of-list marker */
};
+/* callback that gets called when this easy handle is completed within a multi
+ handle. Only used for internally created transfers, like for example
+ DoH. */
+typedef int (*multidone_func)(struct Curl_easy *easy, CURLcode result);
+
struct UserDefined {
FILE *err; /* the stderr user data goes here */
void *debugdata; /* the data that will be passed to fdebug */
@@ -1559,6 +1596,8 @@ struct UserDefined {
curl_proxytype proxytype; /* what kind of proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */
+ size_t upload_buffer_size; /* size of upload buffer to use,
+ keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
@@ -1581,8 +1620,6 @@ struct UserDefined {
/* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially
and they don't change during operations. */
-
- bool printhost; /* printing host name in debug info */
bool get_filetime; /* get the time and get of the remote file */
bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */
bool prefer_ascii; /* ASCII rather than binary */
@@ -1676,7 +1713,7 @@ struct UserDefined {
bool stream_depends_e; /* set or don't set the Exclusive bit */
int stream_weight;
- bool haproxyprotocol; /* whether to send HAProxy PROXY protocol header */
+ bool haproxyprotocol; /* whether to send HAProxy PROXY protocol v1 header */
struct Curl_http2_dep *stream_dependents;
@@ -1685,6 +1722,12 @@ struct UserDefined {
curl_resolver_start_callback resolver_start; /* optional callback called
before resolver start */
void *resolver_start_client; /* pointer to pass to resolver start callback */
+ bool disallow_username_in_url; /* disallow username in url */
+ long upkeep_interval_ms; /* Time between calls for connection upkeep. */
+ bool doh; /* DNS-over-HTTPS enabled */
+ bool doh_get; /* use GET for DoH requests, instead of POST */
+ multidone_func fmultidone;
+ struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
};
struct Names {
@@ -1736,6 +1779,9 @@ struct Curl_easy {
struct to which this "belongs" when used
by the easy interface */
struct Curl_share *share; /* Share, handles global variable mutexing */
+#ifdef USE_LIBPSL
+ struct PslCache *psl; /* The associated PSL cache. */
+#endif
struct SingleRequest req; /* Request-specific data */
struct UserDefined set; /* values set by the libcurl user */
struct DynamicStatic change; /* possibly modified userdefined data */
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index 5d61ce6dc..be6d6111e 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -50,7 +50,7 @@
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
@@ -74,7 +74,7 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
plen = strlen(passwdp);
/* Compute binary message length. Check for overflows. */
- if((ulen > SIZE_T_MAX/2) || (plen > (SIZE_T_MAX/2 - 2)))
+ if((ulen > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2)))
return CURLE_OUT_OF_MEMORY;
plainlen = 2 * ulen + plen + 2;
diff --git a/Utilities/cmcurl/lib/vauth/cram.c b/Utilities/cmcurl/lib/vauth/cram.c
index 3074a163a..d148618b0 100644
--- a/Utilities/cmcurl/lib/vauth/cram.c
+++ b/Utilities/cmcurl/lib/vauth/cram.c
@@ -81,7 +81,7 @@ CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr,
* data [in] - The session handle.
* chlg [in] - The challenge.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index 131d9da8c..ab5156eb7 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.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
@@ -158,7 +158,7 @@ static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
/* Perform quoted-string escaping as described in RFC2616 and its errata */
static char *auth_digest_string_quoted(const char *source)
{
- char *dest, *d;
+ char *dest;
const char *s = source;
size_t n = 1; /* null terminator */
@@ -173,8 +173,8 @@ static char *auth_digest_string_quoted(const char *source)
dest = malloc(n);
if(dest) {
+ char *d = dest;
s = source;
- d = dest;
while(*s) {
if(*s == '"' || *s == '\\') {
*d++ = '\\';
@@ -342,7 +342,7 @@ bool Curl_auth_is_digest_supported(void)
* data [in] - The session handle.
* chlg64 [in] - The base64 encoded challenge message.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
@@ -668,7 +668,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* request [in] - The HTTP request.
* uripath [in] - The path of the HTTP uri.
* digest [in/out] - The digest data struct being used and modified.
@@ -696,7 +696,6 @@ static CURLcode _Curl_auth_create_digest_http_message(
unsigned char ha1[65]; /* 64 digits and 1 zero byte */
unsigned char ha2[65]; /* 64 digits and 1 zero byte */
char userh[65];
- char cnoncebuf[33];
char *cnonce = NULL;
size_t cnonce_sz = 0;
char *userp_quoted;
@@ -707,6 +706,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
digest->nc = 1;
if(!digest->cnonce) {
+ char cnoncebuf[33];
result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
sizeof(cnoncebuf));
if(result)
@@ -781,6 +781,8 @@ static CURLcode _Curl_auth_create_digest_http_message(
*/
hashthis = (unsigned char *) aprintf("%s:%s", request, uripath);
+ if(!hashthis)
+ return CURLE_OUT_OF_MEMORY;
if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment.
@@ -932,7 +934,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* request [in] - The HTTP request.
* uripath [in] - The path of the HTTP uri.
* digest [in/out] - The digest data struct being used and modified.
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index a3f96ed24..928755735 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -75,7 +75,7 @@ bool Curl_auth_is_digest_supported(void)
* data [in] - The session handle.
* chlg64 [in] - The base64 encoded challenge message.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
@@ -391,7 +391,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* request [in] - The HTTP request.
* uripath [in] - The path of the HTTP uri.
* digest [in/out] - The digest data struct being used and modified.
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index 560ecc5bc..55daec1ff 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
@@ -65,7 +65,7 @@ bool Curl_auth_is_gssapi_supported(void)
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in[ - The host name.
* mutual_auth [in] - Flag specifying whether or not mutual authentication
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index 9afb971fc..cb11ed901 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -71,7 +71,7 @@ bool Curl_auth_is_gssapi_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.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* mutual_auth [in] - Flag specifying whether or not mutual authentication
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index cdb8d8f0d..11f42f504 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -354,7 +354,7 @@ 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.
+ * passwdp [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.
@@ -481,7 +481,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* 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.
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index 089c1a6d4..b66cfe737 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -69,7 +69,7 @@ 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.
+ * passwdp [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.
@@ -234,7 +234,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* 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.
diff --git a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
index 5196c2704..4a48bdd20 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
@@ -64,7 +64,7 @@ bool Curl_auth_is_spnego_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.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* chlg64 [in] - The optional base64 encoded challenge message.
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 1fe19e3f9..77d1895a5 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -71,8 +71,8 @@ bool Curl_auth_is_spnego_supported(void)
* Parameters:
*
* data [in] - The session handle.
- * userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * user [in] - The user name in the format User or Domain\User.
+ * password [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* chlg64 [in] - The optional base64 encoded challenge message.
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index 5b0d05a15..05c2cd8b0 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -445,7 +445,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
#ifdef HAVE_BROTLI
version_info.brotli_ver_num = BrotliDecoderVersion();
- brotli_version(brotli_buffer, sizeof brotli_buffer);
+ brotli_version(brotli_buffer, sizeof(brotli_buffer));
version_info.brotli_version = brotli_buffer;
#endif
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index 5ed898b4f..b262392a0 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -29,6 +29,11 @@
#include "curl_setup.h"
#ifdef USE_AXTLS
+
+#error axTLS support has been disabled in curl due to doubts about quality,
+#error user dedication and a lack of use/testing. We urge users to consider
+#error using a more established TLS backend instead.
+
#include <axTLS/config.h>
#include <axTLS/ssl.h>
#include "axtls.h"
diff --git a/Utilities/cmcurl/lib/vtls/axtls.h b/Utilities/cmcurl/lib/vtls/axtls.h
index 3f1e129c2..cb8187272 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.h
+++ b/Utilities/cmcurl/lib/vtls/axtls.h
@@ -31,4 +31,3 @@ extern const struct Curl_ssl Curl_ssl_axtls;
#endif /* USE_AXTLS */
#endif /* HEADER_CURL_AXTLS_H */
-
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 20ce460e8..e10398ac3 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -569,7 +569,7 @@ cyassl_connect_step2(struct connectdata *conn,
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
}
- memset(&x509_parsed, 0, sizeof x509_parsed);
+ memset(&x509_parsed, 0, sizeof(x509_parsed));
if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -968,6 +968,8 @@ static CURLcode Curl_cyassl_random(struct Curl_easy *data,
return CURLE_FAILED_INIT;
if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
return CURLE_FAILED_INIT;
+ if(FreeRng(&rng))
+ return CURLE_FAILED_INIT;
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 45fe49d82..e8116b8a1 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -64,6 +64,7 @@
#define CURL_BUILD_IOS 0
#define CURL_BUILD_IOS_7 0
+#define CURL_BUILD_IOS_9 0
#define CURL_BUILD_IOS_11 0
#define CURL_BUILD_MAC 1
/* This is the maximum API level we are allowed to use when building: */
@@ -72,6 +73,7 @@
#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
+#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
/* These macros mean "the following code is present to allow runtime backward
compatibility with at least this cat or earlier":
@@ -86,6 +88,7 @@
#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
#define CURL_BUILD_IOS 1
#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
+#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
#define CURL_BUILD_MAC 0
#define CURL_BUILD_MAC_10_5 0
@@ -93,6 +96,7 @@
#define CURL_BUILD_MAC_10_7 0
#define CURL_BUILD_MAC_10_8 0
#define CURL_BUILD_MAC_10_9 0
+#define CURL_BUILD_MAC_10_11 0
#define CURL_BUILD_MAC_10_13 0
#define CURL_SUPPORT_MAC_10_5 0
#define CURL_SUPPORT_MAC_10_6 0
@@ -116,6 +120,7 @@
#include "vtls.h"
#include "darwinssl.h"
#include "curl_printf.h"
+#include "strdup.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -945,7 +950,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
if(!c) {
failf(data, "SSL: invalid CA certificate subject");
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_SSL_CACERT;
}
/* If the subject is already available as UTF-8 encoded (ie 'direct') then
@@ -1252,14 +1257,13 @@ static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver,
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_3:
/* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- /* We can assume __builtin_available() will always work in the
- 10.13/11.0 SDK: */
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
*darwinver = kTLSProtocol13;
return CURLE_OK;
}
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+ HAVE_BUILTIN_AVAILABLE == 1 */
break;
}
return CURLE_SSL_CONNECT_ERROR;
@@ -1278,7 +1282,7 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
/* macOS 10.5-10.7 supported TLS 1.0 only.
macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
}
@@ -1287,7 +1291,8 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
}
#else
max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+ HAVE_BUILTIN_AVAILABLE == 1 */
switch(ssl_version) {
case CURL_SSLVERSION_DEFAULT:
@@ -1299,8 +1304,6 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
ssl_version_max = max_supported_version_by_os;
break;
@@ -1430,7 +1433,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
(void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
(void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13);
}
@@ -1439,7 +1442,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
#else
(void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+ HAVE_BUILTIN_AVAILABLE == 1 */
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
@@ -1572,6 +1576,35 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+ if(conn->bits.tls_enable_alpn) {
+ if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+ CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ /* expects length prefixed preference ordered list of protocols in wire
+ * format
+ */
+ err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr);
+ if(err != noErr)
+ infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
+ err);
+ CFRelease(alpnArr);
+ }
+ }
+#endif
+
if(SSL_SET_OPTION(key)) {
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
"Transport. The private key must be in the Keychain.\n");
@@ -1616,6 +1649,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
CFRelease(cert);
+ if(result == CURLE_SSL_CACERT)
+ return CURLE_SSL_CERTPROBLEM;
if(result)
return result;
}
@@ -1751,107 +1786,118 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
higher priority, but it's probably better that we not connect at all than
to give the user a false sense of security if the server only supports
insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
- (void)SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count);
+ err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count);
+ if(err != noErr) {
+ failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
+ err);
+ return CURLE_SSL_CIPHER;
+ }
all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(all_ciphers && allowed_ciphers &&
- SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
- &all_ciphers_count) == noErr) {
- for(i = 0UL ; i < all_ciphers_count ; i++) {
-#if CURL_BUILD_MAC
- /* There's a known bug in early versions of Mountain Lion where ST's ECC
- ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
- Work around the problem here by disabling those ciphers if we are
- running in an affected version of OS X. */
- if(darwinver_maj == 12 && darwinver_min <= 3 &&
- all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
- continue;
- }
-#endif /* CURL_BUILD_MAC */
- switch(all_ciphers[i]) {
- /* Disable NULL ciphersuites: */
- case SSL_NULL_WITH_NULL_NULL:
- case SSL_RSA_WITH_NULL_MD5:
- case SSL_RSA_WITH_NULL_SHA:
- case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
- case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
- case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
- case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
- case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
- case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
- case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
- case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
- case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
- case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
- case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
- case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
- case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
- /* Disable anonymous ciphersuites: */
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- case SSL_DH_anon_WITH_RC4_128_MD5:
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
- case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
- case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
- case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
- case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
- case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
- case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
- case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
- case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
- /* Disable weak key ciphersuites: */
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_RSA_WITH_DES_CBC_SHA:
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- /* Disable IDEA: */
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- /* Disable RC4: */
- case SSL_RSA_WITH_RC4_128_MD5:
- case SSL_RSA_WITH_RC4_128_SHA:
- case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
- case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
- case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
- case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
- case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
- case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
- case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
- break;
- default: /* enable everything else */
- allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
- break;
- }
- }
- err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
- allowed_ciphers_count);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
+ if(!all_ciphers) {
+ failf(data, "SSL: Failed to allocate memory for all ciphers");
+ return CURLE_OUT_OF_MEMORY;
}
- else {
+ allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ if(!allowed_ciphers) {
Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
failf(data, "SSL: Failed to allocate memory for allowed ciphers");
return CURLE_OUT_OF_MEMORY;
}
+ err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
+ &all_ciphers_count);
+ if(err != noErr) {
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ for(i = 0UL ; i < all_ciphers_count ; i++) {
+#if CURL_BUILD_MAC
+ /* There's a known bug in early versions of Mountain Lion where ST's ECC
+ ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
+ Work around the problem here by disabling those ciphers if we are
+ running in an affected version of OS X. */
+ if(darwinver_maj == 12 && darwinver_min <= 3 &&
+ all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
+ continue;
+ }
+#endif /* CURL_BUILD_MAC */
+ switch(all_ciphers[i]) {
+ /* Disable NULL ciphersuites: */
+ case SSL_NULL_WITH_NULL_NULL:
+ case SSL_RSA_WITH_NULL_MD5:
+ case SSL_RSA_WITH_NULL_SHA:
+ case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
+ case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
+ case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
+ case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
+ case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
+ case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
+ case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
+ case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
+ case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
+ case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
+ case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
+ case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
+ case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
+ /* Disable anonymous ciphersuites: */
+ case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_anon_WITH_DES_CBC_SHA:
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
+ case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
+ case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
+ case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+ case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
+ case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
+ case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
+ case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
+ case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
+ /* Disable weak key ciphersuites: */
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ case SSL_DH_DSS_WITH_DES_CBC_SHA:
+ case SSL_DH_RSA_WITH_DES_CBC_SHA:
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ /* Disable IDEA: */
+ case SSL_RSA_WITH_IDEA_CBC_SHA:
+ case SSL_RSA_WITH_IDEA_CBC_MD5:
+ /* Disable RC4: */
+ case SSL_RSA_WITH_RC4_128_MD5:
+ case SSL_RSA_WITH_RC4_128_SHA:
+ case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
+ case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
+ case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
+ case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
+ case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
+ case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
+ case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
+ break;
+ default: /* enable everything else */
+ allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
+ break;
+ }
+ }
+ err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
+ allowed_ciphers_count);
Curl_safefree(all_ciphers);
Curl_safefree(allowed_ciphers);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ return CURLE_SSL_CIPHER;
+ }
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
/* We want to enable 1/n-1 when using a CBC cipher unless the user
@@ -2009,7 +2055,7 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen)
if(len + n >= cap) {
cap *= 2;
- data = realloc(data, cap);
+ data = Curl_saferealloc(data, cap);
if(!data) {
close(fd);
return -1;
@@ -2027,35 +2073,6 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen)
return 0;
}
-static int sslerr_to_curlerr(struct Curl_easy *data, int err)
-{
- switch(err) {
- case errSSLXCertChainInvalid:
- failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_SSL_CACERT;
- case errSSLUnknownRootCert:
- failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_SSL_CACERT;
- case errSSLNoRootCert:
- failf(data, "SSL certificate problem: No root certificate");
- return CURLE_SSL_CACERT;
- case errSSLCertExpired:
- failf(data, "SSL certificate problem: Certificate chain had an "
- "expired certificate");
- return CURLE_SSL_CACERT;
- case errSSLBadCert:
- failf(data, "SSL certificate problem: Couldn't understand the server "
- "certificate format");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLHostNameMismatch:
- failf(data, "SSL certificate peer hostname mismatch");
- return CURLE_PEER_FAILED_VERIFICATION;
- default:
- failf(data, "SSL unexpected certificate error %d", err);
- return CURLE_SSL_CACERT;
- }
-}
-
static int append_cert_to_array(struct Curl_easy *data,
unsigned char *buf, size_t buflen,
CFMutableArrayRef array)
@@ -2073,13 +2090,20 @@ static int append_cert_to_array(struct Curl_easy *data,
CFRelease(certdata);
if(!cacert) {
failf(data, "SSL: failed to create SecCertificate from CA certificate");
- return CURLE_SSL_CACERT;
+ return CURLE_SSL_CACERT_BADFILE;
}
/* Check if cacert is valid. */
result = CopyCertSubject(data, cacert, &certp);
- if(result)
- return result;
+ switch(result) {
+ case CURLE_OK:
+ break;
+ case CURLE_PEER_FAILED_VERIFICATION:
+ return CURLE_SSL_CACERT_BADFILE;
+ case CURLE_OUT_OF_MEMORY:
+ default:
+ return result;
+ }
free(certp);
CFArrayAppendValue(array, cacert);
@@ -2098,7 +2122,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
if(read_cert(cafile, &certbuf, &buflen) < 0) {
failf(data, "SSL: failed to read or invalid CA certificate");
- return CURLE_SSL_CACERT;
+ return CURLE_SSL_CACERT_BADFILE;
}
/*
@@ -2131,7 +2155,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
CFRelease(array);
failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
n, offset);
- return CURLE_SSL_CACERT;
+ return CURLE_SSL_CACERT_BADFILE;
}
offset += res;
@@ -2165,22 +2189,27 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
if(trust == NULL) {
failf(data, "SSL: error getting certificate chain");
CFRelease(array);
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
else if(ret != noErr) {
CFRelease(array);
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SSLCopyPeerTrust() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
ret = SecTrustSetAnchorCertificates(trust, array);
if(ret != noErr) {
+ CFRelease(array);
CFRelease(trust);
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
ret = SecTrustSetAnchorCertificatesOnly(trust, true);
if(ret != noErr) {
+ CFRelease(array);
CFRelease(trust);
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
SecTrustResultType trust_eval = 0;
@@ -2188,7 +2217,8 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
CFRelease(array);
CFRelease(trust);
if(ret != noErr) {
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SecTrustEvaluate() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
switch(trust_eval) {
@@ -2349,6 +2379,53 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
/* the documentation says we need to call SSLHandshake() again */
return darwinssl_connect_step2(conn, sockindex);
+ /* Problem with encrypt / decrypt */
+ case errSSLPeerDecodeError:
+ failf(data, "Decode failed");
+ break;
+ case errSSLDecryptionFail:
+ case errSSLPeerDecryptionFail:
+ failf(data, "Decryption failed");
+ break;
+ case errSSLPeerDecryptError:
+ failf(data, "A decryption error occurred");
+ break;
+ case errSSLBadCipherSuite:
+ failf(data, "A bad SSL cipher suite was encountered");
+ break;
+ case errSSLCrypto:
+ failf(data, "An underlying cryptographic error was encountered");
+ break;
+#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
+ case errSSLWeakPeerEphemeralDHKey:
+ failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
+ break;
+#endif
+
+ /* Problem with the message record validation */
+ case errSSLBadRecordMac:
+ case errSSLPeerBadRecordMac:
+ failf(data, "A record with a bad message authentication code (MAC) "
+ "was encountered");
+ break;
+ case errSSLRecordOverflow:
+ case errSSLPeerRecordOverflow:
+ failf(data, "A record overflow occurred");
+ break;
+
+ /* Problem with zlib decompression */
+ case errSSLPeerDecompressFail:
+ failf(data, "Decompression failed");
+ break;
+
+ /* Problem with access */
+ case errSSLPeerAccessDenied:
+ failf(data, "Access was denied");
+ break;
+ case errSSLPeerInsufficientSecurity:
+ failf(data, "There is insufficient security for this operation");
+ break;
+
/* These are all certificate problems with the server: */
case errSSLXCertChainInvalid:
failf(data, "SSL certificate problem: Invalid certificate chain");
@@ -2359,28 +2436,44 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
case errSSLNoRootCert:
failf(data, "SSL certificate problem: No root certificate");
return CURLE_SSL_CACERT;
+ case errSSLCertNotYetValid:
+ failf(data, "SSL certificate problem: The certificate chain had a "
+ "certificate that is not yet valid");
+ return CURLE_SSL_CACERT;
case errSSLCertExpired:
+ case errSSLPeerCertExpired:
failf(data, "SSL certificate problem: Certificate chain had an "
"expired certificate");
return CURLE_SSL_CACERT;
case errSSLBadCert:
+ case errSSLPeerBadCert:
failf(data, "SSL certificate problem: Couldn't understand the server "
"certificate format");
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CACERT;
+ case errSSLPeerUnsupportedCert:
+ failf(data, "SSL certificate problem: An unsupported certificate "
+ "format was encountered");
+ return CURLE_SSL_CACERT;
+ case errSSLPeerCertRevoked:
+ failf(data, "SSL certificate problem: The certificate was revoked");
+ return CURLE_SSL_CACERT;
+ case errSSLPeerCertUnknown:
+ failf(data, "SSL certificate problem: The certificate is unknown");
+ return CURLE_SSL_CACERT;
/* These are all certificate problems with the client: */
case errSecAuthFailed:
failf(data, "SSL authentication failed");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLPeerHandshakeFail:
failf(data, "SSL peer handshake failed, the server most likely "
"requires a client certificate to connect");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLPeerUnknownCA:
failf(data, "SSL server rejected the client certificate due to "
"the certificate being signed by an unknown certificate "
"authority");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
/* This error is raised if the server's cert didn't match the server's
host name: */
@@ -2389,30 +2482,98 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
"certificate did not match \"%s\"\n", conn->host.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
+ /* Problem with SSL / TLS negotiation */
+ case errSSLNegotiation:
+ failf(data, "Could not negotiate an SSL cipher suite with the server");
+ break;
+ case errSSLBadConfiguration:
+ failf(data, "A configuration error occurred");
+ break;
+ case errSSLProtocol:
+ failf(data, "SSL protocol error");
+ break;
+ case errSSLPeerProtocolVersion:
+ failf(data, "A bad protocol version was encountered");
+ break;
+ case errSSLPeerNoRenegotiation:
+ failf(data, "No renegotiation is allowed");
+ break;
+
/* Generic handshake errors: */
case errSSLConnectionRefused:
failf(data, "Server dropped the connection during the SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLClosedAbort:
failf(data, "Server aborted the SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLNegotiation:
- failf(data, "Could not negotiate an SSL cipher suite with the server");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
+ case errSSLClosedGraceful:
+ failf(data, "The connection closed gracefully");
+ break;
+ case errSSLClosedNoNotify:
+ failf(data, "The server closed the session with no notification");
+ break;
/* Sometimes paramErr happens with buggy ciphers: */
- case paramErr: case errSSLInternal:
+ case paramErr:
+ case errSSLInternal:
+ case errSSLPeerInternalError:
failf(data, "Internal SSL engine error encountered during the "
"SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLFatalAlert:
failf(data, "Fatal SSL engine error encountered during the SSL "
"handshake");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
+ /* Unclassified error */
+ case errSSLBufferOverflow:
+ failf(data, "An insufficient buffer was provided");
+ break;
+ case errSSLIllegalParam:
+ failf(data, "An illegal parameter was encountered");
+ break;
+ case errSSLModuleAttach:
+ failf(data, "Module attach failure");
+ break;
+ case errSSLSessionNotFound:
+ failf(data, "An attempt to restore an unknown session failed");
+ break;
+ case errSSLPeerExportRestriction:
+ failf(data, "An export restriction occurred");
+ break;
+ case errSSLPeerUserCancelled:
+ failf(data, "The user canceled the operation");
+ break;
+ case errSSLPeerUnexpectedMsg:
+ failf(data, "Peer rejected unexpected message");
+ break;
+#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
+ /* Treaing non-fatal error as fatal like before */
+ case errSSLClientHelloReceived:
+ failf(data, "A non-fatal result for providing a server name "
+ "indication");
+ break;
+#endif
+
+ /* Error codes defined in the enum but should never be returned.
+ We list them here just in case. */
+#if CURL_BUILD_MAC_10_6
+ /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
+ case errSSLClientCertRequested:
+ failf(data, "The server has requested a client certificate");
+ break;
+#endif
+#if CURL_BUILD_MAC_10_9
+ /* Alias for errSSLLast, end of error range */
+ case errSSLUnexpectedRecord:
+ failf(data, "Unexpected (skipped) record in DTLS");
+ break;
+#endif
default:
+ /* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
hostname, err);
- return CURLE_SSL_CONNECT_ERROR;
+ break;
}
+ return CURLE_SSL_CONNECT_ERROR;
}
else {
/* we have been connected fine, we're not waiting for anything else. */
@@ -2466,6 +2627,39 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
break;
}
+#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+ if(conn->bits.tls_enable_alpn) {
+ if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+ CFArrayRef alpnArr = NULL;
+ CFStringRef chosenProtocol = NULL;
+ err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr);
+
+ if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
+ chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
+
+#ifdef USE_NGHTTP2
+ if(chosenProtocol &&
+ !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
+ 0)) {
+ conn->negnpn = CURL_HTTP_VERSION_2;
+ }
+ else
+#endif
+ if(chosenProtocol &&
+ !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+
+ /* chosenProtocol is a reference to the string within alpnArr
+ and doesn't need to be freed separately */
+ if(alpnArr)
+ CFRelease(alpnArr);
+ }
+ }
+#endif
+
return CURLE_OK;
}
}
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index b0856cdf4..8d1b3d6af 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -328,7 +328,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
GSKit tokens are always shorter than their cipher names, allocated buffers
will always be large enough to accommodate the result. */
l = strlen(cipherlist) + 1;
- memset((char *) ciphers, 0, sizeof ciphers);
+ memset((char *) ciphers, 0, sizeof(ciphers));
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
ciphers[i].buf = malloc(l);
if(!ciphers[i].buf) {
@@ -536,18 +536,18 @@ inetsocketpair(int sv[2])
lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd < 0)
return -1;
- memset((char *) &addr1, 0, sizeof addr1);
+ memset((char *) &addr1, 0, sizeof(addr1));
addr1.sin_family = AF_INET;
addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr1.sin_port = 0;
- if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
+ if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) ||
listen(lfd, 2) < 0) {
close(lfd);
return -1;
}
/* Get the allocated port. */
- len = sizeof addr1;
+ len = sizeof(addr1);
if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
close(lfd);
return -1;
@@ -562,7 +562,7 @@ inetsocketpair(int sv[2])
/* Request unblocking connection to the listening socket. */
curlx_nonblock(cfd, TRUE);
- if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
+ if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 &&
errno != EINPROGRESS) {
close(lfd);
close(cfd);
@@ -570,7 +570,7 @@ inetsocketpair(int sv[2])
}
/* Get the client dynamic port for intrusion check below. */
- len = sizeof addr2;
+ len = sizeof(addr2);
if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
close(lfd);
close(cfd);
@@ -580,7 +580,7 @@ inetsocketpair(int sv[2])
/* Accept the incoming connection and get the server socket. */
curlx_nonblock(lfd, TRUE);
for(;;) {
- len = sizeof addr1;
+ len = sizeof(addr1);
sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
if(sfd < 0) {
close(lfd);
@@ -644,7 +644,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
i = gsk_secure_soc_read(connproxyssl->backend->handle,
- buf, sizeof buf, &n);
+ buf, sizeof(buf), &n);
switch(i) {
case GSK_OK:
if(n) {
@@ -665,7 +665,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
FD_ISSET(conn->sock[sockindex], &fds_write)) {
/* Pipe data to HTTPS proxy. */
- n = read(BACKEND->remotefd, buf, sizeof buf);
+ n = read(BACKEND->remotefd, buf, sizeof(buf));
if(n < 0)
return -1;
if(n) {
@@ -766,8 +766,6 @@ set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
long i = ssl_version;
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
ssl_version_max = CURL_SSLVERSION_TLSv1_2;
break;
@@ -864,13 +862,13 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
BACKEND->localfd = sockpair[0];
BACKEND->remotefd = sockpair[1];
setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
curlx_nonblock(BACKEND->localfd, TRUE);
curlx_nonblock(BACKEND->remotefd, TRUE);
}
@@ -977,7 +975,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(!result) {
/* Start handshake. Try asynchronous first. */
- memset(&commarea, 0, sizeof commarea);
+ memset(&commarea, 0, sizeof(commarea));
BACKEND->iocport = QsoCreateIOCompletionPort();
if(BACKEND->iocport != -1) {
result = gskit_status(data,
@@ -1316,8 +1314,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
static size_t Curl_gskit_version(char *buffer, size_t size)
{
- strncpy(buffer, "GSKit", size);
- return strlen(buffer);
+ return snprintf(buffer, size, "GSKit");
}
@@ -1333,11 +1330,11 @@ static int Curl_gskit_check_cxn(struct connectdata *cxn)
return 0; /* connection has been closed */
err = 0;
- errlen = sizeof err;
+ errlen = sizeof(err);
if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
(unsigned char *) &err, &errlen) ||
- errlen != sizeof err || err)
+ errlen != sizeof(err) || err)
return 0; /* connection has been closed */
return -1; /* connection status unknown */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 207b0fd1b..37662a748 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -94,6 +94,10 @@ static bool gtls_inited = FALSE;
# endif
#endif
+#if (GNUTLS_VERSION_NUMBER >= 0x030603)
+#define HAS_TLS13
+#endif
+
#ifdef HAS_OCSP
# include <gnutls/ocsp.h>
#endif
@@ -390,9 +394,10 @@ set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
+#ifdef HAS_TLS13
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
+#endif
ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
}
@@ -410,8 +415,13 @@ set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
break;
case CURL_SSLVERSION_TLSv1_3:
+#ifdef HAS_TLS13
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_3;
+ break;
+#else
failf(data, "GnuTLS: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
+#endif
}
}
return CURLE_OK;
@@ -429,13 +439,9 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
struct Curl_easy *data = conn->data;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
- if(ssl_version == CURL_SSLVERSION_TLSv1_3 ||
- ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) {
- failf(data, "GnuTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
- }
+
if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
- ssl_version_max = ssl_version << 16;
+ ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
}
switch(ssl_version | ssl_version_max) {
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
@@ -447,7 +453,6 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
"+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
"+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
return CURLE_OK;
@@ -456,15 +461,54 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
"+VERS-TLS1.1:" GNUTLS_SRP;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
"+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
"+VERS-TLS1.2:" GNUTLS_SRP;
return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
+#ifdef HAS_TLS13
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.3:" GNUTLS_SRP;
+ return CURLE_OK;
+#else
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+#endif
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
}
failf(data, "GnuTLS: cannot set ssl protocol");
@@ -677,6 +721,9 @@ gtls_connect_step1(struct connectdata *conn,
protocol_priority[0] = GNUTLS_TLS1_0;
protocol_priority[1] = GNUTLS_TLS1_1;
protocol_priority[2] = GNUTLS_TLS1_2;
+#ifdef HAS_TLS13
+ protocol_priority[3] = GNUTLS_TLS1_3;
+#endif
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
@@ -709,11 +756,14 @@ gtls_connect_step1(struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_SSLv3:
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
- sni = false;
break;
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
@@ -1102,8 +1152,8 @@ gtls_connect_step3(struct connectdata *conn,
return CURLE_SSL_INVALIDCERTSTATUS;
}
- rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
- &status, NULL, NULL, NULL, &reason);
+ (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
+ &status, NULL, NULL, NULL, &reason);
switch(status) {
case GNUTLS_OCSP_CERT_GOOD:
@@ -1589,7 +1639,7 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
ssize_t result;
int retval = 0;
struct Curl_easy *data = conn->data;
- int done = 0;
+ bool done = FALSE;
char buf[120];
/* This has only been tested on the proftpd server, and the mod_tls code
@@ -1613,7 +1663,7 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
case 0:
/* This is the expected response. There was no data but only
the close notify alert */
- done = 1;
+ done = TRUE;
break;
case GNUTLS_E_AGAIN:
case GNUTLS_E_INTERRUPTED:
@@ -1621,21 +1671,20 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
break;
default:
retval = -1;
- done = 1;
+ done = TRUE;
break;
}
}
else if(0 == what) {
/* timeout */
failf(data, "SSL shutdown timeout");
- done = 1;
- break;
+ done = TRUE;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
retval = -1;
- done = 1;
+ done = TRUE;
}
}
gnutls_deinit(BACKEND->session);
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index d7759dc84..c5ed8872e 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -205,14 +205,11 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
ssl_version = CURL_SSLVERSION_TLSv1_0;
- ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
}
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c
new file mode 100644
index 000000000..6a2b67e63
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/mesalink.c
@@ -0,0 +1,627 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2017, 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 all MesaLink-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+/*
+ * Based upon the CyaSSL implementation in cyassl.c and cyassl.h:
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * Thanks for code and inspiration!
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_MESALINK
+
+#include <mesalink/options.h>
+#include <mesalink/version.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "strcase.h"
+#include "x509asn1.h"
+#include "curl_printf.h"
+
+#include "mesalink.h"
+#include <mesalink/openssl/ssl.h>
+#include <mesalink/openssl/err.h>
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MESALINK_MAX_ERROR_SZ 80
+
+struct ssl_backend_data
+{
+ SSL_CTX *ctx;
+ SSL *handle;
+};
+
+#define BACKEND connssl->backend
+
+static Curl_recv mesalink_recv;
+static Curl_send mesalink_send;
+
+/*
+ * This function loads all the client/CA certificates and CRLs. Setup the TLS
+ * layer and do all necessary magic.
+ */
+static CURLcode
+mesalink_connect_step1(struct connectdata *conn, int sockindex)
+{
+ char *ciphers;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const char *const ssl_capath = SSL_CONN_CONFIG(CApath);
+ struct in_addr addr4;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+ const char *const hostname =
+ SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name;
+ size_t hostname_len = strlen(hostname);
+
+ SSL_METHOD *req_method = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+
+ if(connssl->state == ssl_connection_complete)
+ return CURLE_OK;
+
+ if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "MesaLink does not support to set maximum SSL/TLS version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ switch(SSL_CONN_CONFIG(version)) {
+ case CURL_SSLVERSION_SSLv3:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ failf(data, "MesaLink does not support SSL 3.0, TLS 1.0, or TLS 1.1");
+ return CURLE_NOT_BUILT_IN;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1_2:
+ req_method = TLSv1_2_client_method();
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ req_method = TLSv1_3_client_method();
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ failf(data, "MesaLink does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(!req_method) {
+ failf(data, "SSL: couldn't create a method!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(BACKEND->ctx)
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = SSL_CTX_new(req_method);
+
+ if(!BACKEND->ctx) {
+ failf(data, "SSL: couldn't create a context!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ SSL_CTX_set_verify(
+ BACKEND->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+
+ if(ssl_cafile || ssl_capath) {
+ if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) {
+ if(verifypeer) {
+ failf(data,
+ "error setting certificate verify locations:\n"
+ " CAfile: %s\n CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ infof(data,
+ "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ else {
+ infof(data, "successfully set certificate verify locations:\n");
+ }
+ infof(data,
+ " CAfile: %s\n"
+ " CApath: %s\n",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ }
+
+ ciphers = SSL_CONN_CONFIG(cipher_list);
+ if(ciphers) {
+#ifdef MESALINK_HAVE_CIPHER
+ if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+#endif
+ infof(data, "Cipher selection: %s\n", ciphers);
+ }
+
+ if(BACKEND->handle)
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = SSL_new(BACKEND->ctx);
+ if(!BACKEND->handle) {
+ failf(data, "SSL: couldn't create a context (handle)!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if((hostname_len < USHRT_MAX) &&
+ (0 == Curl_inet_pton(AF_INET, hostname, &addr4))
+#ifdef ENABLE_IPV6
+ && (0 == Curl_inet_pton(AF_INET6, hostname, &addr6))
+#endif
+ ) {
+ /* hostname is not a valid IP address */
+ if(SSL_set_tlsext_host_name(BACKEND->handle, hostname) != SSL_SUCCESS) {
+ failf(data,
+ "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+#ifdef CURLDEBUG
+ /* Check if the hostname is 127.0.0.1 or [::1];
+ * otherwise reject because MesaLink always wants a valid DNS Name
+ * specified in RFC 5280 Section 7.2 */
+ if(strncmp(hostname, "127.0.0.1", 9) == 0
+#ifdef ENABLE_IPV6
+ || strncmp(hostname, "[::1]", 5) == 0
+#endif
+ ) {
+ SSL_set_tlsext_host_name(BACKEND->handle, "localhost");
+ }
+ else
+#endif
+ {
+ failf(data,
+ "ERROR: MesaLink does not accept an IP address as a hostname\n");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+#ifdef MESALINK_HAVE_SESSION
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ void *ssl_sessionid = NULL;
+
+ Curl_ssl_sessionid_lock(conn);
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
+ Curl_ssl_sessionid_unlock(conn);
+ failf(
+ data,
+ "SSL: SSL_set_session failed: %s",
+ ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof(data, "SSL re-using session ID\n");
+ }
+ Curl_ssl_sessionid_unlock(conn);
+ }
+#endif /* MESALINK_HAVE_SESSION */
+
+ if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) {
+ failf(data, "SSL: SSL_set_fd failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+static CURLcode
+mesalink_connect_step2(struct connectdata *conn, int sockindex)
+{
+ int ret = -1;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ conn->recv[sockindex] = mesalink_recv;
+ conn->send[sockindex] = mesalink_send;
+
+ ret = SSL_connect(BACKEND->handle);
+ if(ret != SSL_SUCCESS) {
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
+ int detail = SSL_get_error(BACKEND->handle, ret);
+
+ if(SSL_ERROR_WANT_CONNECT == detail) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ else {
+ failf(data,
+ "SSL_connect failed with error %d: %s",
+ detail,
+ ERR_error_string_n(detail, error_buffer, sizeof(error_buffer)));
+ ERR_print_errors_fp(stderr);
+ if(detail && SSL_CONN_CONFIG(verifypeer)) {
+ detail &= ~0xFF;
+ if(detail == TLS_ERROR_WEBPKI_ERRORS) {
+ failf(data, "Cert verify failed");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_3;
+ infof(data,
+ "SSL connection using %s / %s\n",
+ SSL_get_version(BACKEND->handle),
+ SSL_get_cipher_name(BACKEND->handle));
+
+ return CURLE_OK;
+}
+
+static CURLcode
+mesalink_connect_step3(struct connectdata *conn, int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+#ifdef MESALINK_HAVE_SESSION
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ bool incache;
+ SSL_SESSION *our_ssl_sessionid;
+ void *old_ssl_sessionid = NULL;
+
+ our_ssl_sessionid = SSL_get_session(BACKEND->handle);
+
+ Curl_ssl_sessionid_lock(conn);
+ incache =
+ !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ result = Curl_ssl_addsessionid(
+ conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
+ if(result) {
+ Curl_ssl_sessionid_unlock(conn);
+ failf(data, "failed to store ssl session");
+ return result;
+ }
+ }
+ Curl_ssl_sessionid_unlock(conn);
+ }
+#endif /* MESALINK_HAVE_SESSION */
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return result;
+}
+
+static ssize_t
+mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
+ size_t len, CURLcode *curlcode)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
+ int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ int rc = SSL_write(BACKEND->handle, mem, memlen);
+
+ if(rc < 0) {
+ int err = SSL_get_error(BACKEND->handle, rc);
+ switch(err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_write() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data,
+ "SSL write: %s, errno %d",
+ ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
+ SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+ return rc;
+}
+
+static void
+Curl_mesalink_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(BACKEND->handle) {
+ (void)SSL_shutdown(BACKEND->handle);
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
+ }
+ if(BACKEND->ctx) {
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = NULL;
+ }
+}
+
+static ssize_t
+mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
+ CURLcode *curlcode)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
+ int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ int nread = SSL_read(BACKEND->handle, buf, buffsize);
+
+ if(nread <= 0) {
+ int err = SSL_get_error(BACKEND->handle, nread);
+
+ switch(err) {
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ case IO_ERROR_CONNECTION_ABORTED:
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_read() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data,
+ "SSL read: %s, errno %d",
+ ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ return nread;
+}
+
+static size_t
+Curl_mesalink_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
+}
+
+static int
+Curl_mesalink_init(void)
+{
+ return (SSL_library_init() == SSL_SUCCESS);
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+static int
+Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
+{
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(BACKEND->handle) {
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
+ }
+ return retval;
+}
+
+static CURLcode
+mesalink_connect_common(struct connectdata *conn, int sockindex,
+ bool nonblocking, bool *done)
+{
+ CURLcode result;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ time_t timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = mesalink_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd =
+ ssl_connect_2_writing == connssl->connecting_state ? sockfd
+ : CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state
+ ? sockfd
+ : CURL_SOCKET_BAD;
+
+ what = Curl_socket_check(
+ readfd, CURL_SOCKET_BAD, writefd, nonblocking ? 0 : timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ result = mesalink_connect_step2(conn, sockindex);
+
+ if(result ||
+ (nonblocking && (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state))) {
+ return result;
+ }
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = mesalink_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = mesalink_recv;
+ conn->send[sockindex] = mesalink_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ return mesalink_connect_common(conn, sockindex, TRUE, done);
+}
+
+static CURLcode
+Curl_mesalink_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = mesalink_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+static void *
+Curl_mesalink_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_mesalink = {
+ { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */
+
+ SSLSUPP_SSL_CTX,
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_mesalink_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_mesalink_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_mesalink_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_mesalink_connect, /* connect */
+ Curl_mesalink_connect_nonblocking, /* connect_nonblocking */
+ Curl_mesalink_get_internals, /* get_internals */
+ Curl_mesalink_close, /* close_one */
+ Curl_none_close_all, /* close_all */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ 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 */
+};
+
+#endif
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.h b/Utilities/cmcurl/lib/vtls/mesalink.h
new file mode 100644
index 000000000..54cb94ad3
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/mesalink.h
@@ -0,0 +1,32 @@
+#ifndef HEADER_CURL_MESALINK_H
+#define HEADER_CURL_MESALINK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2017, 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 USE_MESALINK
+
+extern const struct Curl_ssl Curl_ssl_mesalink;
+
+#endif /* USE_MESALINK */
+#endif /* HEADER_CURL_MESALINK_H */
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 7cd450cda..a3d3e58bb 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -217,10 +217,15 @@ static const cipher_s cipherlist[] = {
#endif
};
+#ifdef WIN32
+static const char *pem_library = "nsspem.dll";
+static const char *trust_library = "nssckbi.dll";
+#else
static const char *pem_library = "libnsspem.so";
-static SECMODModule *pem_module = NULL;
-
static const char *trust_library = "libnssckbi.so";
+#endif
+
+static SECMODModule *pem_module = NULL;
static SECMODModule *trust_module = NULL;
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
@@ -394,7 +399,7 @@ static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
/* wrap 'ptr' as list node and tail-insert into 'list' */
static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
{
- struct ptr_list_wrap *wrap = malloc(sizeof *wrap);
+ struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
if(!wrap)
return CURLE_OUT_OF_MEMORY;
@@ -914,11 +919,11 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
PRTime now;
int i;
- if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
- SECSuccess && channel.length == sizeof channel &&
+ if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
+ SECSuccess && channel.length == sizeof(channel) &&
channel.cipherSuite) {
if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
- &suite, sizeof suite) == SECSuccess) {
+ &suite, sizeof(suite)) == SECSuccess) {
infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
}
}
@@ -1345,7 +1350,8 @@ static CURLcode nss_init(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* the default methods just call down to the lower I/O layer */
- memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods);
+ memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(),
+ sizeof(nspr_io_methods));
/* override certain methods in the table by our wrappers */
nspr_io_methods.recv = nspr_io_recv;
@@ -1521,7 +1527,6 @@ static bool is_nss_error(CURLcode err)
{
switch(err) {
case CURLE_PEER_FAILED_VERIFICATION:
- case CURLE_SSL_CACERT:
case CURLE_SSL_CERTPROBLEM:
case CURLE_SSL_CONNECT_ERROR:
case CURLE_SSL_ISSUER_ERROR:
@@ -1578,8 +1583,9 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
infof(data, "%s %s\n", (result) ? "failed to load" : "loaded",
trust_library);
if(result == CURLE_FAILED_INIT)
- /* make the error non-fatal if we are not going to verify peer */
- result = CURLE_SSL_CACERT_BADFILE;
+ /* If libnssckbi.so is not available (or fails to load), one can still
+ use CA certificates stored in NSS database. Ignore the failure. */
+ result = CURLE_OK;
}
else if(!use_trust_module && trust_module) {
/* libnssckbi.so not needed but already loaded --> unload it! */
@@ -1714,8 +1720,6 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
return result;
}
- if(max == CURL_SSLVERSION_MAX_NONE)
- sslver->max = sslver->min;
}
switch(max) {
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index f6a4bd3fb..4c5e8c19c 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -50,9 +50,6 @@
#include "hostcheck.h"
#include "curl_printf.h"
#include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_DSA
@@ -72,6 +69,12 @@
#include <openssl/ocsp.h>
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && /* 0.9.8 or later */ \
+ !defined(OPENSSL_NO_ENGINE)
+#define USE_OPENSSL_ENGINE
+#include <openssl/engine.h>
+#endif
+
#include "warnless.h"
#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */
@@ -83,7 +86,7 @@
#error "OPENSSL_VERSION_NUMBER not defined"
#endif
-#if defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
#include <openssl/ui.h>
#endif
@@ -126,16 +129,15 @@
#define X509_get0_notBefore(x) X509_get_notBefore(x)
#define X509_get0_notAfter(x) X509_get_notAfter(x)
#define CONST_EXTS /* nope */
-#ifdef LIBRESSL_VERSION_NUMBER
-static unsigned long OpenSSL_version_num(void)
-{
- return LIBRESSL_VERSION_NUMBER;
-}
-#else
+#ifndef LIBRESSL_VERSION_NUMBER
#define OpenSSL_version_num() SSLeay()
#endif
#endif
+#ifdef LIBRESSL_VERSION_NUMBER
+#define OpenSSL_version_num() LIBRESSL_VERSION_NUMBER
+#endif
+
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
!(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x20700000L)
@@ -166,6 +168,18 @@ static unsigned long OpenSSL_version_num(void)
#define HAVE_KEYLOG_CALLBACK
#endif
+/* Whether SSL_CTX_set_ciphersuites is available.
+ * OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
+ * BoringSSL: no
+ * LibreSSL: no
+ */
+#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL))
+#define HAVE_SSL_CTX_SET_CIPHERSUITES
+#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+#endif
+
#if defined(LIBRESSL_VERSION_NUMBER)
#define OSSL_PACKAGE "LibreSSL"
#elif defined(OPENSSL_IS_BORINGSSL)
@@ -239,7 +253,7 @@ static void ossl_keylog_callback(const SSL *ssl, const char *line)
if(!buf)
return;
}
- strncpy(buf, line, linelen);
+ memcpy(buf, line, linelen);
buf[linelen] = '\n';
buf[linelen + 1] = '\0';
@@ -504,7 +518,7 @@ static int do_file_type(const char *type)
return -1;
}
-#if defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
/*
* Supply default password to the engine user interface conversation.
* The password is passed by OpenSSL engine from ENGINE_load_private_key()
@@ -544,8 +558,20 @@ static int ssl_ui_writer(UI *ui, UI_STRING *uis)
}
return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
}
+
+/*
+ * Check if a given string is a PKCS#11 URI
+ */
+static bool is_pkcs11_uri(const char *string)
+{
+ return (string && strncasecompare(string, "pkcs11:", 7));
+}
+
#endif
+static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
+ const char *engine);
+
static
int cert_stuff(struct connectdata *conn,
SSL_CTX* ctx,
@@ -606,8 +632,18 @@ int cert_stuff(struct connectdata *conn,
}
break;
case SSL_FILETYPE_ENGINE:
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
+#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
{
+ /* Implicitly use pkcs11 engine if none was provided and the
+ * cert_file is a PKCS#11 URI */
+ if(!data->state.engine) {
+ if(is_pkcs11_uri(cert_file)) {
+ if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ return 0;
+ }
+ }
+ }
+
if(data->state.engine) {
const char *cmd_name = "LOAD_CERT_CTRL";
struct {
@@ -781,9 +817,20 @@ int cert_stuff(struct connectdata *conn,
}
break;
case SSL_FILETYPE_ENGINE:
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
{ /* XXXX still needs some work */
EVP_PKEY *priv_key = NULL;
+
+ /* Implicitly use pkcs11 engine if none was provided and the
+ * key_file is a PKCS#11 URI */
+ if(!data->state.engine) {
+ if(is_pkcs11_uri(key_file)) {
+ if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ return 0;
+ }
+ }
+ }
+
if(data->state.engine) {
UI_METHOD *ui_method =
UI_create_method((char *)"curl user interface");
@@ -931,7 +978,7 @@ static int Curl_ossl_init(void)
OPENSSL_load_builtin_modules();
-#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
+#ifdef USE_OPENSSL_ENGINE
ENGINE_load_builtin_engines();
#endif
@@ -947,9 +994,11 @@ static int Curl_ossl_init(void)
#define CONF_MFLAGS_DEFAULT_SECTION 0x0
#endif
+#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
CONF_modules_load_file(NULL, NULL,
CONF_MFLAGS_DEFAULT_SECTION|
CONF_MFLAGS_IGNORE_MISSING_FILE);
+#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
@@ -1088,7 +1137,7 @@ static int Curl_ossl_check_cxn(struct connectdata *conn)
static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
const char *engine)
{
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
ENGINE *e;
#if OPENSSL_VERSION_NUMBER >= 0x00909000L
@@ -1133,7 +1182,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
*/
static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
{
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
infof(data, "set default crypto engine '%s'\n",
@@ -1156,7 +1205,7 @@ static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
struct curl_slist *beg;
ENGINE *e;
@@ -1213,7 +1262,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
ssize_t nread;
int buffsize;
int err;
- int done = 0;
+ bool done = FALSE;
/* This has only been tested on the proftpd server, and the mod_tls code
sends a close notify alert without waiting for a close notify alert in
@@ -1241,7 +1290,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
case SSL_ERROR_ZERO_RETURN: /* no more data */
/* This is the expected response. There was no data but only
the close notify alert */
- done = 1;
+ done = TRUE;
break;
case SSL_ERROR_WANT_READ:
/* there's data pending, re-invoke SSL_read() */
@@ -1250,7 +1299,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
case SSL_ERROR_WANT_WRITE:
/* SSL wants a write. Really odd. Let's bail out. */
infof(data, "SSL_ERROR_WANT_WRITE\n");
- done = 1;
+ done = TRUE;
break;
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
@@ -1260,20 +1309,20 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
ossl_strerror(sslerror, buf, sizeof(buf)) :
SSL_ERROR_to_str(err)),
SOCKERRNO);
- done = 1;
+ done = TRUE;
break;
}
}
else if(0 == what) {
/* timeout */
failf(data, "SSL shutdown timeout");
- done = 1;
+ done = TRUE;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
retval = -1;
- done = 1;
+ done = TRUE;
}
} /* while()-loop for the select() */
@@ -1312,7 +1361,7 @@ static void Curl_ossl_session_free(void *ptr)
*/
static void Curl_ossl_close_all(struct Curl_easy *data)
{
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
ENGINE_finish(data->state.engine);
ENGINE_free(data->state.engine);
@@ -1369,6 +1418,10 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
}
#else
{
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)dispname;
+ (void)data;
+#endif
if(Curl_cert_hostcheck(match_pattern, hostname)) {
infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
dispname, match_pattern);
@@ -1922,7 +1975,15 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
}
else
#endif
- {
+ if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ msg_type = *(char *)buf;
+ msg_name = "Change cipher spec";
+ }
+ else if(content_type == SSL3_RT_ALERT) {
+ msg_type = (((char *)buf)[0] << 8) + ((char *)buf)[1];
+ msg_name = SSL_alert_desc_string_long(msg_type);
+ }
+ else {
msg_type = *(char *)buf;
msg_name = ssl_msg_type(ssl_ver, msg_type);
}
@@ -1931,12 +1992,12 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
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, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
}
}
Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
- CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
+ CURLINFO_SSL_DATA_IN, (char *)buf, len);
(void) ssl;
}
#endif
@@ -2025,6 +2086,7 @@ select_next_proto_cb(SSL *ssl,
}
#endif /* HAS_NPN */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
static const char *
get_ssl_version_txt(SSL *ssl)
{
@@ -2051,6 +2113,7 @@ get_ssl_version_txt(SSL *ssl)
}
return "unknown";
}
+#endif
static CURLcode
set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
@@ -2064,10 +2127,6 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
- if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
- ssl_version_max = ssl_version << 16;
- }
-
switch(ssl_version) {
case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
@@ -2099,8 +2158,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
#endif
/* FALLTHROUGH */
case CURL_SSLVERSION_TLSv1_0:
- *ctx_options |= SSL_OP_NO_SSLv2;
- *ctx_options |= SSL_OP_NO_SSLv3;
+ case CURL_SSLVERSION_TLSv1:
break;
}
@@ -2116,7 +2174,6 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
#endif
/* FALLTHROUGH */
case CURL_SSLVERSION_MAX_TLSv1_2:
- case CURL_SSLVERSION_MAX_DEFAULT:
#ifdef TLS1_3_VERSION
*ctx_options |= SSL_OP_NO_TLSv1_3;
#endif
@@ -2305,11 +2362,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
switch(ssl_version) {
case CURL_SSLVERSION_SSLv3:
-#ifdef USE_TLS_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP) {
- infof(data, "Set version TLSv1.x for SRP authorisation\n");
- }
-#endif
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_TLSv1;
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
@@ -2323,21 +2375,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- break;
-
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
+ /* asking for any TLS version as the minimum, means no SSL versions
+ allowed */
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
case CURL_SSLVERSION_SSLv2:
-#ifndef OPENSSL_NO_SSL2
ctx_options |= SSL_OP_NO_SSLv3;
ctx_options |= SSL_OP_NO_TLSv1;
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
@@ -2348,10 +2399,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#endif
#endif
break;
-#else
- failf(data, OSSL_PACKAGE " was built without SSLv2 support");
- return CURLE_NOT_BUILT_IN;
-#endif
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@@ -2414,6 +2461,24 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "Cipher selection: %s\n", ciphers);
}
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+ {
+ char *ciphers13 = SSL_CONN_CONFIG(cipher_list13);
+ if(ciphers13) {
+ if(!SSL_CTX_set_ciphersuites(BACKEND->ctx, ciphers13)) {
+ failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13);
+ }
+ }
+#endif
+
+#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+ /* OpenSSL 1.1.1 requires clients to opt-in for PHA */
+ SSL_CTX_set_post_handshake_auth(BACKEND->ctx, 1);
+#endif
+
#ifdef USE_TLS_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP) {
char * const ssl_username = SSL_SET_OPTION(username);
@@ -2468,7 +2533,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
#ifdef CURL_CA_FALLBACK
else if(verifypeer) {
- /* verfying the peer without any CA certificates won't
+ /* verifying the peer without any CA certificates won't
work so use openssl's built in default as fallback */
SSL_CTX_set_default_verify_paths(BACKEND->ctx);
}
@@ -3134,7 +3199,7 @@ static CURLcode servercert(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
int rc;
- long lerr, len;
+ long lerr;
struct Curl_easy *data = conn->data;
X509 *issuer;
BIO *fp = NULL;
@@ -3157,7 +3222,7 @@ static CURLcode servercert(struct connectdata *conn,
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)) );
BIO_free(mem);
- return 0;
+ return CURLE_OUT_OF_MEMORY;
}
BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
@@ -3177,15 +3242,20 @@ static CURLcode servercert(struct connectdata *conn,
buffer, sizeof(buffer));
infof(data, " subject: %s\n", rc?"[NONE]":buffer);
- ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
- len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " start date: %.*s\n", len, ptr);
- (void)BIO_reset(mem);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ {
+ long len;
+ ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
+ len = BIO_get_mem_data(mem, (char **) &ptr);
+ infof(data, " start date: %.*s\n", len, ptr);
+ (void)BIO_reset(mem);
- ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
- len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " expire date: %.*s\n", len, ptr);
- (void)BIO_reset(mem);
+ ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
+ len = BIO_get_mem_data(mem, (char **) &ptr);
+ infof(data, " expire date: %.*s\n", len, ptr);
+ (void)BIO_reset(mem);
+ }
+#endif
BIO_free(mem);
@@ -3204,7 +3274,7 @@ static CURLcode servercert(struct connectdata *conn,
if(rc) {
if(strict)
failf(data, "SSL: couldn't get X509-issuer name!");
- result = CURLE_SSL_CONNECT_ERROR;
+ result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
infof(data, " issuer: %s\n", buffer);
@@ -3754,6 +3824,9 @@ const struct Curl_ssl Curl_ssl_openssl = {
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_SSL_CTX |
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+ SSLSUPP_TLS13_CIPHERSUITES |
+#endif
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 604cb4c86..27af0ccf3 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -185,14 +185,11 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
ssl_version = CURL_SSLVERSION_TLSv1_0;
- ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
}
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 2cfd5c19f..e4426924b 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -90,11 +90,17 @@
#endif
#endif
+#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
+#ifdef HAS_CLIENT_CERT_PATH
#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
+#endif
#ifndef SP_PROT_SSL2_CLIENT
#define SP_PROT_SSL2_CLIENT 0x00000008
@@ -174,8 +180,6 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
@@ -199,6 +203,155 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
return CURLE_OK;
}
+/*longest is 26, buffer is slightly bigger*/
+#define LONGEST_ALG_ID 32
+#define CIPHEROPTION(X) \
+if(strcmp(#X, tmp) == 0) \
+ return X
+
+static int
+get_alg_id_by_name(char *name)
+{
+ char tmp[LONGEST_ALG_ID] = { 0 };
+ char *nameEnd = strchr(name, ':');
+ size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \
+ min(strlen(name), LONGEST_ALG_ID - 1);
+ strncpy(tmp, name, n);
+ tmp[n] = 0;
+ CIPHEROPTION(CALG_MD2);
+ CIPHEROPTION(CALG_MD4);
+ CIPHEROPTION(CALG_MD5);
+ CIPHEROPTION(CALG_SHA);
+ CIPHEROPTION(CALG_SHA1);
+ CIPHEROPTION(CALG_MAC);
+ CIPHEROPTION(CALG_RSA_SIGN);
+ CIPHEROPTION(CALG_DSS_SIGN);
+/*ifdefs for the options that are defined conditionally in wincrypt.h*/
+#ifdef CALG_NO_SIGN
+ CIPHEROPTION(CALG_NO_SIGN);
+#endif
+ CIPHEROPTION(CALG_RSA_KEYX);
+ CIPHEROPTION(CALG_DES);
+#ifdef CALG_3DES_112
+ CIPHEROPTION(CALG_3DES_112);
+#endif
+ CIPHEROPTION(CALG_3DES);
+ CIPHEROPTION(CALG_DESX);
+ CIPHEROPTION(CALG_RC2);
+ CIPHEROPTION(CALG_RC4);
+ CIPHEROPTION(CALG_SEAL);
+#ifdef CALG_DH_SF
+ CIPHEROPTION(CALG_DH_SF);
+#endif
+ CIPHEROPTION(CALG_DH_EPHEM);
+#ifdef CALG_AGREEDKEY_ANY
+ CIPHEROPTION(CALG_AGREEDKEY_ANY);
+#endif
+#ifdef CALG_HUGHES_MD5
+ CIPHEROPTION(CALG_HUGHES_MD5);
+#endif
+ CIPHEROPTION(CALG_SKIPJACK);
+#ifdef CALG_TEK
+ CIPHEROPTION(CALG_TEK);
+#endif
+ CIPHEROPTION(CALG_CYLINK_MEK);
+ CIPHEROPTION(CALG_SSL3_SHAMD5);
+#ifdef CALG_SSL3_MASTER
+ CIPHEROPTION(CALG_SSL3_MASTER);
+#endif
+#ifdef CALG_SCHANNEL_MASTER_HASH
+ CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH);
+#endif
+#ifdef CALG_SCHANNEL_MAC_KEY
+ CIPHEROPTION(CALG_SCHANNEL_MAC_KEY);
+#endif
+#ifdef CALG_SCHANNEL_ENC_KEY
+ CIPHEROPTION(CALG_SCHANNEL_ENC_KEY);
+#endif
+#ifdef CALG_PCT1_MASTER
+ CIPHEROPTION(CALG_PCT1_MASTER);
+#endif
+#ifdef CALG_SSL2_MASTER
+ CIPHEROPTION(CALG_SSL2_MASTER);
+#endif
+#ifdef CALG_TLS1_MASTER
+ CIPHEROPTION(CALG_TLS1_MASTER);
+#endif
+#ifdef CALG_RC5
+ CIPHEROPTION(CALG_RC5);
+#endif
+#ifdef CALG_HMAC
+ CIPHEROPTION(CALG_HMAC);
+#endif
+#if !defined(__W32API_MAJOR_VERSION) || \
+ !defined(__W32API_MINOR_VERSION) || \
+ defined(__MINGW64_VERSION_MAJOR) || \
+ (__W32API_MAJOR_VERSION > 5) || \
+ ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
+ /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
+ see https://osdn.net/projects/mingw/ticket/38391 */
+ CIPHEROPTION(CALG_TLS1PRF);
+#endif
+#ifdef CALG_HASH_REPLACE_OWF
+ CIPHEROPTION(CALG_HASH_REPLACE_OWF);
+#endif
+#ifdef CALG_AES_128
+ CIPHEROPTION(CALG_AES_128);
+#endif
+#ifdef CALG_AES_192
+ CIPHEROPTION(CALG_AES_192);
+#endif
+#ifdef CALG_AES_256
+ CIPHEROPTION(CALG_AES_256);
+#endif
+#ifdef CALG_AES
+ CIPHEROPTION(CALG_AES);
+#endif
+#ifdef CALG_SHA_256
+ CIPHEROPTION(CALG_SHA_256);
+#endif
+#ifdef CALG_SHA_384
+ CIPHEROPTION(CALG_SHA_384);
+#endif
+#ifdef CALG_SHA_512
+ CIPHEROPTION(CALG_SHA_512);
+#endif
+#ifdef CALG_ECDH
+ CIPHEROPTION(CALG_ECDH);
+#endif
+#ifdef CALG_ECMQV
+ CIPHEROPTION(CALG_ECMQV);
+#endif
+#ifdef CALG_ECDSA
+ CIPHEROPTION(CALG_ECDSA);
+#endif
+ return 0;
+}
+
+static CURLcode
+set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
+{
+ char *startCur = ciphers;
+ int algCount = 0;
+ static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
+ while(startCur && (0 != *startCur) && (algCount < 45)) {
+ long alg = strtol(startCur, 0, 0);
+ if(!alg)
+ alg = get_alg_id_by_name(startCur);
+ if(alg)
+ algIds[algCount++] = alg;
+ else
+ return CURLE_SSL_CIPHER;
+ startCur = strchr(startCur, ':');
+ if(startCur)
+ startCur++;
+ }
+ schannel_cred->palgSupportedAlgs = algIds;
+ schannel_cred->cSupportedAlgs = algCount;
+ return CURLE_OK;
+}
+
+#ifdef HAS_CLIENT_CERT_PATH
static CURLcode
get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
TCHAR **thumbprint)
@@ -208,7 +361,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
sep = _tcschr(path, TEXT('\\'));
if(sep == NULL)
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
store_name_len = sep - path;
@@ -232,22 +385,23 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
else
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
*store_path = sep + 1;
sep = _tcschr(*store_path, TEXT('\\'));
if(sep == NULL)
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
*sep = 0;
*thumbprint = sep + 1;
if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
return CURLE_OK;
}
+#endif
static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
@@ -299,10 +453,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#endif
#ifdef _WIN32_WCE
+#ifdef HAS_MANUAL_VERIFY_API
/* 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
+#error "compiler too old to support requisite manual cert verify for Win CE"
+#endif
+#else
+#ifdef HAS_MANUAL_VERIFY_API
if(SSL_CONN_CONFIG(CAfile)) {
if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
@@ -316,6 +475,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
else
BACKEND->use_manual_cred_validation = false;
+#else
+ if(SSL_CONN_CONFIG(CAfile)) {
+ failf(data, "schannel: CA cert support not built in");
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
#endif
BACKEND->cred = NULL;
@@ -341,9 +506,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
if(conn->ssl_config.verifypeer) {
+#ifdef HAS_MANUAL_VERIFY_API
if(BACKEND->use_manual_cred_validation)
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
else
+#endif
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
/* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
@@ -401,6 +568,16 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
+ if(SSL_CONN_CONFIG(cipher_list)) {
+ result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
+ if(CURLE_OK != result) {
+ failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
+ return result;
+ }
+ }
+
+
+#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
if(data->set.ssl.cert) {
DWORD cert_store_name;
@@ -417,16 +594,23 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
result = get_cert_location(cert_path, &cert_store_name,
&cert_store_path, &cert_thumbprint_str);
if(result != CURLE_OK) {
+ failf(data, "schannel: Failed to get certificate location for %s",
+ cert_path);
Curl_unicodefree(cert_path);
return result;
}
- cert_store = CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
- (HCRYPTPROV)NULL,
- cert_store_name, cert_store_path);
+ cert_store =
+ CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
+ cert_store_path);
if(!cert_store) {
+ failf(data, "schannel: Failed to open cert store %x %s, "
+ "last error is %x",
+ cert_store_name, cert_store_path, GetLastError());
Curl_unicodefree(cert_path);
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
}
cert_thumbprint.pbData = cert_thumbprint_data;
@@ -437,7 +621,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
cert_thumbprint_data, &cert_thumbprint.cbData,
NULL, NULL)) {
Curl_unicodefree(cert_path);
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
}
client_certs[0] = CertFindCertificateInStore(
@@ -450,9 +634,19 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
schannel_cred.cCreds = 1;
schannel_cred.paCred = client_certs;
}
+ else {
+ /* CRYPT_E_NOT_FOUND / E_INVALIDARG */
+ return CURLE_SSL_CERTPROBLEM;
+ }
CertCloseStore(cert_store, 0);
}
+#else
+ if(data->set.ssl.cert) {
+ failf(data, "schannel: client cert support not built in");
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
/* allocate memory for the re-usable credential handle */
BACKEND->cred = (struct curl_schannel_cred *)
@@ -480,14 +674,20 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
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",
- Curl_sspi_strerror(conn, sspi_status));
- else
- failf(data, "schannel: AcquireCredentialsHandle failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
+ failf(data, "schannel: AcquireCredentialsHandle failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(BACKEND->cred);
- return CURLE_SSL_CONNECT_ERROR;
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_SECPKG_NOT_FOUND:
+ case SEC_E_NOT_OWNER:
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ case SEC_E_INTERNAL_ERROR:
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
}
@@ -590,14 +790,32 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
Curl_unicodefree(host_name);
if(sspi_status != SEC_I_CONTINUE_NEEDED) {
- if(sspi_status == SEC_E_WRONG_PRINCIPAL)
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- else
- failf(data, "schannel: initial InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(BACKEND->ctxt);
- return CURLE_SSL_CONNECT_ERROR;
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_WRONG_PRINCIPAL:
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_PEER_FAILED_VERIFICATION;
+ /*
+ case SEC_E_INVALID_HANDLE:
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_LOGON_DENIED:
+ case SEC_E_TARGET_UNKNOWN:
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ case SEC_E_INTERNAL_ERROR:
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ */
+ default:
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
infof(data, "schannel: sending initial handshake data: "
@@ -812,14 +1030,31 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
}
else {
- if(sspi_status == SEC_E_WRONG_PRINCIPAL)
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- else
- failf(data, "schannel: next InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- return sspi_status == SEC_E_UNTRUSTED_ROOT ?
- CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR;
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_WRONG_PRINCIPAL:
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_PEER_FAILED_VERIFICATION;
+ /*
+ case SEC_E_INVALID_HANDLE:
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_LOGON_DENIED:
+ case SEC_E_TARGET_UNKNOWN:
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ case SEC_E_INTERNAL_ERROR:
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ */
+ default:
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
/* check if there was additional remaining encrypted data */
@@ -877,9 +1112,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
}
+#ifdef HAS_MANUAL_VERIFY_API
if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
return verify_certificate(conn, sockindex);
}
+#endif
return CURLE_OK;
}
@@ -998,7 +1235,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
failf(data, "schannel: failed to retrieve remote cert context");
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
result = Curl_ssl_init_certinfo(data, 1);
@@ -1819,7 +2056,7 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
x509_der = (const char *)pCertContextServer->pbCertEncoded;
x509_der_len = pCertContextServer->cbCertEncoded;
- memset(&x509_parsed, 0, sizeof x509_parsed);
+ memset(&x509_parsed, 0, sizeof(x509_parsed));
if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
break;
@@ -1870,7 +2107,8 @@ static void Curl_schannel_checksum(const unsigned char *input,
if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
break; /* failed */
- if(!CryptHashData(hHash, (const BYTE*)input, (DWORD)inputlen, 0))
+ /* workaround for original MinGW, should be (const BYTE*) */
+ if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
break; /* failed */
/* get hash size */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 447690027..e491bd431 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -32,12 +32,44 @@
#include "urldata.h"
+/* <wincrypt.h> has been included via the above <schnlsp.h>.
+ * Or in case of ldap.c, it was included via <winldap.h>.
+ * And since <wincrypt.h> has this:
+ * #define X509_NAME ((LPCSTR) 7)
+ *
+ * And in BoringSSL's <openssl/base.h> there is:
+ * typedef struct X509_name_st X509_NAME;
+ * etc.
+ *
+ * this will cause all kinds of C-preprocessing paste errors in
+ * BoringSSL's <openssl/x509.h>: So just undefine those defines here
+ * (and only here).
+ */
+#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL)
+# undef X509_NAME
+# undef X509_CERT_PAIR
+# undef X509_EXTENSIONS
+#endif
+
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
+
+#ifdef __MINGW32__
+#include <_mingw.h>
+#ifdef __MINGW64_VERSION_MAJOR
+#define HAS_MANUAL_VERIFY_API
+#endif
+#else
+#include <wincrypt.h>
+#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
+#define HAS_MANUAL_VERIFY_API
+#endif
+#endif
+
struct curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
@@ -66,7 +98,9 @@ struct ssl_backend_data {
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 */
+#ifdef HAS_MANUAL_VERIFY_API
bool use_manual_cred_validation; /* true if manual cred validation is used */
+#endif
};
#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index db187dd6b..2516f5665 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -30,14 +30,15 @@
#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
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
#include "schannel.h"
+
+#ifdef HAS_MANUAL_VERIFY_API
+
#include "vtls.h"
#include "sendf.h"
#include "strerror.h"
@@ -53,7 +54,7 @@
#define BACKEND connssl->backend
#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
-#define BEGIN_CERT "-----BEGIN CERTIFICATE-----\n"
+#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
#define END_CERT "\n-----END CERTIFICATE-----"
typedef struct {
@@ -71,6 +72,10 @@ typedef struct {
HCERTSTORE hExclusiveTrustedPeople;
} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
+static int is_cr_or_lf(char c)
+{
+ return c == '\r' || c == '\n';
+}
static CURLcode add_certs_to_store(HCERTSTORE trust_store,
const char *ca_file,
@@ -130,7 +135,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
failf(data,
"schannel: CA file exceeds max size of %u bytes",
MAX_CAFILE_SIZE);
- result = CURLE_OUT_OF_MEMORY;
+ result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
@@ -177,7 +182,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
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) {
+ if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) {
more_certs = 0;
}
else {
@@ -209,7 +214,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
NULL,
NULL,
NULL,
- &cert_context)) {
+ (const void **)&cert_context)) {
failf(data,
"schannel: failed to extract certificate from CA file "
@@ -239,7 +244,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
CertFreeCertificateContext(cert_context);
if(!add_cert_result) {
failf(data,
- "schannel: failed to add certificate from CA file '%s'"
+ "schannel: failed to add certificate from CA file '%s' "
"to certificate store: %s",
ca_file, Curl_strerror(conn, GetLastError()));
result = CURLE_SSL_CACERT_BADFILE;
@@ -314,6 +319,10 @@ static CURLcode verify_host(struct Curl_easy *data,
* embedded null bytes. This appears to be undocumented behavior.
*/
cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR));
+ if(!cert_hostname_buff) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
actual_len = CertGetNameString(pCertContextServer,
CERT_NAME_DNS_TYPE,
name_flags,
@@ -548,4 +557,5 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex)
return result;
}
+#endif /* HAS_MANUAL_VERIFY_API */
#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index ee5bc7a0a..6af39feab 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -96,7 +96,8 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
- Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
+ Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
+ Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13))
return TRUE;
return FALSE;
@@ -119,6 +120,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(random_file);
CLONE_STRING(egdsocket);
CLONE_STRING(cipher_list);
+ CLONE_STRING(cipher_list13);
return TRUE;
}
@@ -131,6 +133,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
Curl_safefree(sslc->random_file);
Curl_safefree(sslc->egdsocket);
Curl_safefree(sslc->cipher_list);
+ Curl_safefree(sslc->cipher_list13);
}
#ifdef USE_SSL
@@ -980,6 +983,14 @@ bool Curl_ssl_false_start(void)
}
/*
+ * Check whether the SSL backend supports setting TLS 1.3 cipher suites
+ */
+bool Curl_ssl_tls13_ciphersuites(void)
+{
+ return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
+}
+
+/*
* Default implementations for unsupported functions.
*/
@@ -1179,6 +1190,8 @@ const struct Curl_ssl *Curl_ssl =
&Curl_ssl_polarssl;
#elif defined(USE_SCHANNEL)
&Curl_ssl_schannel;
+#elif defined(USE_MESALINK)
+ &Curl_ssl_mesalink;
#else
#error "Missing struct Curl_ssl for selected SSL backend"
#endif
@@ -1214,6 +1227,9 @@ static const struct Curl_ssl *available_backends[] = {
#if defined(USE_SCHANNEL)
&Curl_ssl_schannel,
#endif
+#if defined(USE_MESALINK)
+ &Curl_ssl_mesalink,
+#endif
NULL
};
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index e7b87c4d3..5cd11602e 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -31,6 +31,7 @@ struct ssl_connect_data;
#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 */
+#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */
struct Curl_ssl {
/*
@@ -93,6 +94,7 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
+bool Curl_ssl_tls13_ciphersuites(void);
CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
unsigned char *md5sum, size_t md5len);
@@ -106,6 +108,7 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
#include "schannel.h" /* Schannel SSPI version */
#include "darwinssl.h" /* SecureTransport (Darwin) version */
#include "mbedtls.h" /* mbedTLS versions */
+#include "mesalink.h" /* MesaLink versions */
#ifndef MAX_PINNED_PUBKEY_SIZE
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
@@ -246,7 +249,7 @@ bool Curl_ssl_false_start(void);
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
-#else
+#else /* if not USE_SSL */
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
@@ -270,6 +273,7 @@ bool Curl_ssl_false_start(void);
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
#define Curl_ssl_false_start() FALSE
+#define Curl_ssl_tls13_ciphersuites() FALSE
#endif
#endif /* HEADER_CURL_VTLS_H */
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index f6a2d744b..284ea1e75 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -26,6 +26,9 @@
#include <curl/curl.h> /* for curl_socket_t */
#endif
+#define CURLX_FUNCTION_CAST(target_type, func) \
+ (target_type)(void (*) (void))(func)
+
unsigned short curlx_ultous(unsigned long ulnum);
unsigned char curlx_ultouc(unsigned long ulnum);
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index bba20233f..a576fc703 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.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
@@ -40,10 +40,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-/* For overflow checks. */
-#define CURL_SIZE_T_MAX ((size_t)-1)
-
-
/* ASN.1 OIDs. */
static const char cnOID[] = "2.5.4.3"; /* Common name. */
static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */
@@ -107,9 +103,12 @@ static const curl_OID OIDtable[] = {
* Please note there is no pretention here to rewrite a full SSL library.
*/
+static const char *getASN1Element(curl_asn1Element *elem,
+ const char *beg, const char *end)
+ WARN_UNUSED_RESULT;
-const char *Curl_getASN1Element(curl_asn1Element *elem,
- const char *beg, const char *end)
+static const char *getASN1Element(curl_asn1Element *elem,
+ const char *beg, const char *end)
{
unsigned char b;
unsigned long len;
@@ -146,7 +145,7 @@ const char *Curl_getASN1Element(curl_asn1Element *elem,
return (const char *) NULL;
elem->beg = beg;
while(beg < end && *beg) {
- beg = Curl_getASN1Element(&lelem, beg, end);
+ beg = getASN1Element(&lelem, beg, end);
if(!beg)
return (const char *) NULL;
}
@@ -206,7 +205,7 @@ static const char *octet2str(const char *beg, const char *end)
/* Convert an ASN.1 octet string to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
- if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
+ if(n <= (SIZE_T_MAX - 1) / 3) {
buf = malloc(3 * n + 1);
if(buf)
for(n = 0; beg < end; n += 3)
@@ -227,7 +226,7 @@ static const char *bit2str(const char *beg, const char *end)
static const char *int2str(const char *beg, const char *end)
{
- long val = 0;
+ unsigned long val = 0;
size_t n = end - beg;
/* Convert an ASN.1 integer value into its string representation.
@@ -247,7 +246,7 @@ static const char *int2str(const char *beg, const char *end)
do
val = (val << 8) | *(const unsigned char *) beg++;
while(beg < end);
- return curl_maprintf("%s%lx", (val < 0 || val >= 10)? "0x": "", val);
+ return curl_maprintf("%s%lx", val >= 10? "0x": "", val);
}
static ssize_t
@@ -287,7 +286,7 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
if(inlength % size)
return -1; /* Length inconsistent with character size. */
- if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
+ if(inlength / size > (SIZE_T_MAX - 1) / 4)
return -1; /* Too big. */
buf = malloc(4 * (inlength / size) + 1);
if(!buf)
@@ -306,10 +305,10 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
case 4:
wc = (wc << 8) | *(const unsigned char *) from++;
wc = (wc << 8) | *(const unsigned char *) from++;
- /* fallthrough */
+ /* FALLTHROUGH */
case 2:
wc = (wc << 8) | *(const unsigned char *) from++;
- /* fallthrough */
+ /* FALLTHROUGH */
default: /* case 1: */
wc = (wc << 8) | *(const unsigned char *) from++;
}
@@ -546,7 +545,7 @@ static const char *UTime2str(const char *beg, const char *end)
tzl, tzp);
}
-const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
+static const char *ASN1tostr(curl_asn1Element *elem, int type)
{
/* Convert an ASN.1 element to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
@@ -605,12 +604,19 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
Return the total string length, even if larger than `n'. */
for(p1 = dn->beg; p1 < dn->end;) {
- p1 = Curl_getASN1Element(&rdn, p1, dn->end);
+ p1 = getASN1Element(&rdn, p1, dn->end);
+ if(!p1)
+ return -1;
for(p2 = rdn.beg; p2 < rdn.end;) {
- p2 = Curl_getASN1Element(&atv, p2, rdn.end);
- p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
- Curl_getASN1Element(&value, p3, atv.end);
- str = Curl_ASN1tostr(&oid, 0);
+ p2 = getASN1Element(&atv, p2, rdn.end);
+ if(!p2)
+ return -1;
+ p3 = getASN1Element(&oid, atv.beg, atv.end);
+ if(!p3)
+ return -1;
+ if(!getASN1Element(&value, p3, atv.end))
+ return -1;
+ str = ASN1tostr(&oid, 0);
if(!str)
return -1;
@@ -640,7 +646,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
l++;
/* Generate value. */
- str = Curl_ASN1tostr(&value, 0);
+ str = ASN1tostr(&value, 0);
if(!str)
return -1;
for(p3 = str; *p3; p3++) {
@@ -655,7 +661,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
return l;
}
-const char *Curl_DNtostr(curl_asn1Element *dn)
+static const char *DNtostr(curl_asn1Element *dn)
{
char *buf = (char *) NULL;
ssize_t n = encodeDN(buf, 0, dn);
@@ -694,17 +700,22 @@ int Curl_parseX509(curl_X509certificate *cert,
cert->certificate.end = end;
/* Get the sequence content. */
- if(!Curl_getASN1Element(&elem, beg, end))
+ if(!getASN1Element(&elem, beg, end))
return -1; /* Invalid bounds/size. */
beg = elem.beg;
end = elem.end;
/* Get tbsCertificate. */
- beg = Curl_getASN1Element(&tbsCertificate, beg, end);
+ beg = getASN1Element(&tbsCertificate, beg, end);
+ if(!beg)
+ return -1;
/* Skip the signatureAlgorithm. */
- beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
+ if(!beg)
+ return -1;
/* Get the signatureValue. */
- Curl_getASN1Element(&cert->signature, beg, end);
+ if(!getASN1Element(&cert->signature, beg, end))
+ return -1;
/* Parse TBSCertificate. */
beg = tbsCertificate.beg;
@@ -712,30 +723,49 @@ int Curl_parseX509(curl_X509certificate *cert,
/* Get optional version, get serialNumber. */
cert->version.header = NULL;
cert->version.beg = &defaultVersion;
- cert->version.end = &defaultVersion + sizeof defaultVersion;;
- beg = Curl_getASN1Element(&elem, beg, end);
+ cert->version.end = &defaultVersion + sizeof(defaultVersion);
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
if(elem.tag == 0) {
- Curl_getASN1Element(&cert->version, elem.beg, elem.end);
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(!getASN1Element(&cert->version, elem.beg, elem.end))
+ return -1;
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
}
cert->serialNumber = elem;
/* Get signature algorithm. */
- beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
/* Get issuer. */
- beg = Curl_getASN1Element(&cert->issuer, beg, end);
+ beg = getASN1Element(&cert->issuer, beg, end);
+ if(!beg)
+ return -1;
/* Get notBefore and notAfter. */
- beg = Curl_getASN1Element(&elem, beg, end);
- ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
- Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ ccp = getASN1Element(&cert->notBefore, elem.beg, elem.end);
+ if(!ccp)
+ return -1;
+ if(!getASN1Element(&cert->notAfter, ccp, elem.end))
+ return -1;
/* Get subject. */
- beg = Curl_getASN1Element(&cert->subject, beg, end);
+ beg = getASN1Element(&cert->subject, beg, end);
+ if(!beg)
+ return -1;
/* Get subjectPublicKeyAlgorithm and subjectPublicKey. */
- beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
- ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
- cert->subjectPublicKeyInfo.beg,
- cert->subjectPublicKeyInfo.end);
- Curl_getASN1Element(&cert->subjectPublicKey, ccp,
- cert->subjectPublicKeyInfo.end);
+ beg = getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
+ if(!beg)
+ return -1;
+ ccp = getASN1Element(&cert->subjectPublicKeyAlgorithm,
+ cert->subjectPublicKeyInfo.beg,
+ cert->subjectPublicKeyInfo.end);
+ if(!ccp)
+ return -1;
+ if(!getASN1Element(&cert->subjectPublicKey, ccp,
+ cert->subjectPublicKeyInfo.end))
+ return -1;
/* Get optional issuerUiqueID, subjectUniqueID and extensions. */
cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
cert->extensions.tag = elem.tag = 0;
@@ -744,20 +774,30 @@ int Curl_parseX509(curl_X509certificate *cert,
cert->subjectUniqueID.beg = cert->subjectUniqueID.end = "";
cert->extensions.header = NULL;
cert->extensions.beg = cert->extensions.end = "";
- if(beg < end)
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(beg < end) {
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ }
if(elem.tag == 1) {
cert->issuerUniqueID = elem;
- if(beg < end)
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(beg < end) {
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ }
}
if(elem.tag == 2) {
cert->subjectUniqueID = elem;
- if(beg < end)
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(beg < end) {
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ }
}
if(elem.tag == 3)
- Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+ if(!getASN1Element(&cert->extensions, elem.beg, elem.end))
+ return -1;
return 0;
}
@@ -785,12 +825,15 @@ static const char *dumpAlgo(curl_asn1Element *param,
/* Get algorithm parameters and return algorithm name. */
- beg = Curl_getASN1Element(&oid, beg, end);
+ beg = getASN1Element(&oid, beg, end);
+ if(!beg)
+ return NULL;
param->header = NULL;
param->tag = 0;
param->beg = param->end = end;
if(beg < end)
- Curl_getASN1Element(param, beg, end);
+ if(!getASN1Element(param, beg, end))
+ return NULL;
return OID2str(oid.beg, oid.end, TRUE);
}
@@ -801,7 +844,7 @@ static void do_pubkey_field(struct Curl_easy *data, int certnum,
/* Generate a certificate information record for the public key. */
- output = Curl_ASN1tostr(elem, 0);
+ output = ASN1tostr(elem, 0);
if(output) {
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, label, output);
@@ -825,10 +868,14 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
/* Generate all information records for the public key. */
/* Get the public key (single element). */
- Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
+ if(!getASN1Element(&pk, pubkey->beg + 1, pubkey->end))
+ return;
if(strcasecompare(algo, "rsaEncryption")) {
- p = Curl_getASN1Element(&elem, pk.beg, pk.end);
+ p = getASN1Element(&elem, pk.beg, pk.end);
+ if(!p)
+ return;
+
/* Compute key length. */
for(q = elem.beg; !*q && q < elem.end; q++)
;
@@ -849,30 +896,34 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
}
/* Generate coefficients. */
do_pubkey_field(data, certnum, "rsa(n)", &elem);
- Curl_getASN1Element(&elem, p, pk.end);
+ if(!getASN1Element(&elem, p, pk.end))
+ return;
do_pubkey_field(data, certnum, "rsa(e)", &elem);
}
else if(strcasecompare(algo, "dsa")) {
- p = Curl_getASN1Element(&elem, param->beg, param->end);
- do_pubkey_field(data, certnum, "dsa(p)", &elem);
- p = Curl_getASN1Element(&elem, p, param->end);
- do_pubkey_field(data, certnum, "dsa(q)", &elem);
- Curl_getASN1Element(&elem, p, param->end);
- do_pubkey_field(data, certnum, "dsa(g)", &elem);
- do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
+ p = getASN1Element(&elem, param->beg, param->end);
+ if(p) {
+ do_pubkey_field(data, certnum, "dsa(p)", &elem);
+ p = getASN1Element(&elem, p, param->end);
+ if(p) {
+ do_pubkey_field(data, certnum, "dsa(q)", &elem);
+ if(getASN1Element(&elem, p, param->end)) {
+ do_pubkey_field(data, certnum, "dsa(g)", &elem);
+ do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
+ }
+ }
+ }
}
else if(strcasecompare(algo, "dhpublicnumber")) {
- p = Curl_getASN1Element(&elem, param->beg, param->end);
- do_pubkey_field(data, certnum, "dh(p)", &elem);
- Curl_getASN1Element(&elem, param->beg, param->end);
- do_pubkey_field(data, certnum, "dh(g)", &elem);
- do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
- }
-#if 0 /* Patent-encumbered. */
- else if(strcasecompare(algo, "ecPublicKey")) {
- /* Left TODO. */
+ p = getASN1Element(&elem, param->beg, param->end);
+ if(p) {
+ do_pubkey_field(data, certnum, "dh(p)", &elem);
+ if(getASN1Element(&elem, param->beg, param->end)) {
+ do_pubkey_field(data, certnum, "dh(g)", &elem);
+ do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
+ }
+ }
}
-#endif
}
CURLcode Curl_extract_certinfo(struct connectdata *conn,
@@ -900,10 +951,10 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
/* Extract the certificate ASN.1 elements. */
if(Curl_parseX509(&cert, beg, end))
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_PEER_FAILED_VERIFICATION;
/* Subject. */
- ccp = Curl_DNtostr(&cert.subject);
+ ccp = DNtostr(&cert.subject);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
@@ -913,7 +964,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
free((char *) ccp);
/* Issuer. */
- ccp = Curl_DNtostr(&cert.issuer);
+ ccp = DNtostr(&cert.issuer);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
@@ -937,7 +988,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
/* Serial number. */
- ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
+ ccp = ASN1tostr(&cert.serialNumber, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
@@ -958,7 +1009,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
free((char *) ccp);
/* Start Date. */
- ccp = Curl_ASN1tostr(&cert.notBefore, 0);
+ ccp = ASN1tostr(&cert.notBefore, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
@@ -968,7 +1019,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
free((char *) ccp);
/* Expire Date. */
- ccp = Curl_ASN1tostr(&cert.notAfter, 0);
+ ccp = ASN1tostr(&cert.notAfter, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
@@ -992,7 +1043,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
/* TODO: extensions. */
/* Signature. */
- ccp = Curl_ASN1tostr(&cert.signature, 0);
+ ccp = ASN1tostr(&cert.signature, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
@@ -1051,7 +1102,7 @@ static const char *checkOID(const char *beg, const char *end,
/* Check if first ASN.1 element at `beg' is the given OID.
Return a pointer in the source after the OID if found, else NULL. */
- ccp = Curl_getASN1Element(&e, beg, end);
+ ccp = getASN1Element(&e, beg, end);
if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
return (const char *) NULL;
@@ -1110,19 +1161,30 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
/* Process extensions. */
for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
- p = Curl_getASN1Element(&ext, p, cert.extensions.end);
+ p = getASN1Element(&ext, p, cert.extensions.end);
+ if(!p)
+ return CURLE_PEER_FAILED_VERIFICATION;
+
/* Check if extension is a subjectAlternativeName. */
ext.beg = checkOID(ext.beg, ext.end, sanOID);
if(ext.beg) {
- ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ ext.beg = getASN1Element(&elem, ext.beg, ext.end);
+ if(!ext.beg)
+ return CURLE_PEER_FAILED_VERIFICATION;
/* Skip critical if present. */
- if(elem.tag == CURL_ASN1_BOOLEAN)
- ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ if(elem.tag == CURL_ASN1_BOOLEAN) {
+ ext.beg = getASN1Element(&elem, ext.beg, ext.end);
+ if(!ext.beg)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
/* Parse the octet string contents: is a single sequence. */
- Curl_getASN1Element(&elem, elem.beg, elem.end);
+ if(!getASN1Element(&elem, elem.beg, elem.end))
+ return CURLE_PEER_FAILED_VERIFICATION;
/* Check all GeneralNames. */
for(q = elem.beg; matched != 1 && q < elem.end;) {
- q = Curl_getASN1Element(&name, q, elem.end);
+ q = getASN1Element(&name, q, elem.end);
+ if(!q)
+ break;
switch(name.tag) {
case 2: /* DNS name. */
len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
@@ -1135,8 +1197,8 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
break;
case 7: /* IP address. */
- matched = (size_t) (name.end - q) == addrlen &&
- !memcmp(&addr, q, addrlen);
+ matched = (size_t) (name.end - name.beg) == addrlen &&
+ !memcmp(&addr, name.beg, addrlen);
break;
}
}
@@ -1162,9 +1224,13 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
/* we have to look to the last occurrence of a commonName in the
distinguished one to get the most significant one. */
while(q < cert.subject.end) {
- q = Curl_getASN1Element(&dn, q, cert.subject.end);
+ q = getASN1Element(&dn, q, cert.subject.end);
+ if(!q)
+ break;
for(p = dn.beg; p < dn.end;) {
- p = Curl_getASN1Element(&elem, p, dn.end);
+ p = getASN1Element(&elem, p, dn.end);
+ if(!p)
+ return CURLE_PEER_FAILED_VERIFICATION;
/* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
elem.beg = checkOID(elem.beg, elem.end, cnOID);
if(elem.beg)
@@ -1173,7 +1239,7 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
}
/* Check the CN if found. */
- if(!Curl_getASN1Element(&elem, name.beg, name.end))
+ if(!getASN1Element(&elem, name.beg, name.end))
failf(data, "SSL: unable to obtain common name from peer certificate");
else {
len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index 206f3c6a5..d7af6e2b6 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -71,6 +71,7 @@ include(CTest)
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
+OPTION(ENABLE_LZ4 "Enable the use of the system LZ4 library if found" ON)
OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON)
@@ -328,7 +329,7 @@ IF(ENABLE_LZO)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
ELSE(ENABLE_LZO)
- SET(LIBZMA_FOUND FALSE) # Override cached value
+ SET(LZO2_FOUND FALSE) # Override cached value
ENDIF(ENABLE_LZO)
IF(LZO2_FOUND)
SET(HAVE_LIBLZO2 1)
@@ -347,15 +348,19 @@ IF(0) # CMake does not need LZ4 support in libarchive
#
# Find LZ4
#
-IF (LZ4_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LZ4_FIND_QUIETLY TRUE)
-ENDIF (LZ4_INCLUDE_DIR)
+IF(ENABLE_LZ4)
+ IF (LZ4_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZ4_FIND_QUIETLY TRUE)
+ ENDIF (LZ4_INCLUDE_DIR)
-FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
-FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+ FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
+ FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+ELSE(ENABLE_LZ4)
+ SET(LZ4_FOUND FALSE) # Override cached value
+ENDIF(ENABLE_LZ4)
IF(LZ4_FOUND)
SET(HAVE_LIBLZ4 1)
SET(HAVE_LZ4_H 1)
@@ -371,6 +376,31 @@ IF(LZ4_FOUND)
ENDIF(LZ4_FOUND)
MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY)
+#
+# Find Zstd
+#
+IF (ZSTD_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(ZSTD_FIND_QUIETLY TRUE)
+ENDIF (ZSTD_INCLUDE_DIR)
+
+FIND_PATH(ZSTD_INCLUDE_DIR zstd.h)
+FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
+IF(ZSTD_FOUND)
+ SET(HAVE_ZSTD_H 1)
+ INCLUDE_DIRECTORIES(${ZSTD_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${ZSTD_LIBRARY})
+ SET(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY})
+ SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
+ CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_LIBZSTD)
+ #
+ # TODO: test for static library.
+ #
+ENDIF(ZSTD_FOUND)
+MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
ENDIF()
#
@@ -451,6 +481,7 @@ LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H)
+LA_CHECK_INCLUDE_FILE("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H)
LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H)
LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H)
diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in
index 368a451e2..1851d81d0 100644
--- a/Utilities/cmlibarchive/build/cmake/config.h.in
+++ b/Utilities/cmlibarchive/build/cmake/config.h.in
@@ -728,6 +728,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `z' library (-lz). */
#cmakedefine HAVE_LIBZ 1
+/* Define to 1 if you have the `zstd' library (-lzstd). */
+#cmakedefine HAVE_LIBZSTD 1
+
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H 1
@@ -1071,6 +1074,10 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#cmakedefine HAVE_SYS_SYSMACROS_H 1
+
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
@@ -1185,6 +1192,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
+/* Define to 1 if you have the <zstd.h> header file. */
+#cmakedefine HAVE_ZSTD_H 1
+
/* Define to 1 if you have the `_ctime64_s' function. */
#cmakedefine HAVE__CTIME64_S 1
diff --git a/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in b/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in
index 95d715951..4b631e635 100644
--- a/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in
+++ b/Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in
@@ -7,5 +7,6 @@ Name: libarchive
Description: library that can create and read several streaming archive formats
Version: @VERSION@
Cflags: -I${includedir}
+Cflags.private: -DLIBARCHIVE_STATIC
Libs: -L${libdir} -larchive
Libs.private: @LIBS@
diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version
index 2dd083974..2427eab0f 100644
--- a/Utilities/cmlibarchive/build/version
+++ b/Utilities/cmlibarchive/build/version
@@ -1 +1 @@
-3003002
+3003003
diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
index b02ae828e..e38d66453 100644
--- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
@@ -88,6 +88,7 @@ SET(libarchive_SOURCES
archive_read_support_filter_rpm.c
archive_read_support_filter_uu.c
archive_read_support_filter_xz.c
+ archive_read_support_filter_zstd.c
archive_read_support_format_7zip.c
archive_read_support_format_all.c
archive_read_support_format_ar.c
@@ -134,6 +135,7 @@ SET(libarchive_SOURCES
archive_write_add_filter_program.c
archive_write_add_filter_uuencode.c
archive_write_add_filter_xz.c
+ archive_write_add_filter_zstd.c
archive_write_set_format.c
archive_write_set_format_7zip.c
archive_write_set_format_ar.c
diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h
index 0f94d2e6c..f3ebbfe42 100644
--- a/Utilities/cmlibarchive/libarchive/archive.h
+++ b/Utilities/cmlibarchive/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3003002
+#define ARCHIVE_VERSION_NUMBER 3003003
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -152,7 +152,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.3.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.3"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -174,6 +174,7 @@ __LA_DECL const char * archive_zlib_version(void);
__LA_DECL const char * archive_liblzma_version(void);
__LA_DECL const char * archive_bzlib_version(void);
__LA_DECL const char * archive_liblz4_version(void);
+__LA_DECL const char * archive_libzstd_version(void);
/* Declare our basic types. */
struct archive;
@@ -273,6 +274,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_FILTER_LZOP 11
#define ARCHIVE_FILTER_GRZIP 12
#define ARCHIVE_FILTER_LZ4 13
+#define ARCHIVE_FILTER_ZSTD 14
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@@ -430,6 +432,7 @@ __LA_DECL int archive_read_support_filter_program_signature
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
__LA_DECL int archive_read_support_filter_uu(struct archive *);
__LA_DECL int archive_read_support_filter_xz(struct archive *);
+__LA_DECL int archive_read_support_filter_zstd(struct archive *);
__LA_DECL int archive_read_support_format_7zip(struct archive *);
__LA_DECL int archive_read_support_format_all(struct archive *);
@@ -775,6 +778,7 @@ __LA_DECL int archive_write_add_filter_program(struct archive *,
const char *cmd);
__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
__LA_DECL int archive_write_add_filter_xz(struct archive *);
+__LA_DECL int archive_write_add_filter_zstd(struct archive *);
/* A convenience function to set the format based on the code or name. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c
index b8b6b6364..4736531af 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_acl.c
@@ -1159,6 +1159,7 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
switch (want_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ __LA_FALLTHROUGH;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
numfields = 5;
@@ -1626,6 +1627,7 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text,
switch (want_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ __LA_FALLTHROUGH;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
numfields = 5;
diff --git a/Utilities/cmlibarchive/libarchive/archive_cmdline.c b/Utilities/cmlibarchive/libarchive/archive_cmdline.c
index 7d3bac53b..5c519cd17 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cmdline.c
+++ b/Utilities/cmlibarchive/libarchive/archive_cmdline.c
@@ -100,10 +100,10 @@ get_argument(struct archive_string *as, const char *p)
/*
* Set up command line arguments.
- * Returns ARChIVE_OK if everything okey.
- * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
+ * Returns ARCHIVE_OK if everything okey.
+ * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
* empty command line.
- * Returns ARChIVE_FATAL if no memory.
+ * Returns ARCHIVE_FATAL if no memory.
*/
int
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor.c b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
index ced52fd70..71967c9d4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cryptor.c
+++ b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
@@ -153,7 +153,7 @@ aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
CCCryptorStatus r;
r = CCCryptorReset(ref, NULL);
- if (r != kCCSuccess)
+ if (r != kCCSuccess && r != kCCUnimplemented)
return -1;
r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
AES_BLOCK_SIZE, NULL);
diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h b/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
index 0ca544b57..b9759220d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
@@ -64,7 +64,7 @@ typedef struct {
} archive_crypto_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-#include <Bcrypt.h>
+#include <bcrypt.h>
/* Common in other bcrypt implementations, but missing from VS2008. */
#ifndef BCRYPT_SUCCESS
diff --git a/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c b/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c
index 07d08ff96..aba41e5da 100644
--- a/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c
+++ b/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c
@@ -93,7 +93,9 @@ static const acl_perm_map_t acl_nfs4_flag_map[] = {
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+#ifdef ACL_ENTRY_INHERITED
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif
};
static const int acl_nfs4_flag_map_size =
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c
index 30fb4566e..f722bbe85 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.c
@@ -1491,7 +1491,7 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
* the style of the generated ACL.
*/
wchar_t *
-archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
+archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
int flags)
{
return (archive_acl_to_text_w(&entry->acl, len, flags,
@@ -1499,7 +1499,7 @@ archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
}
char *
-archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
+archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
int flags)
{
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h
index 8c8e75a1b..a9134f6b6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3003002
+#define ARCHIVE_VERSION_NUMBER 3003003
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -42,6 +42,7 @@
#include <sys/types.h>
#include <stddef.h> /* for wchar_t */
+#include <stdint.h>
#include <time.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c
index be72066ea..f150e8224 100644
--- a/Utilities/cmlibarchive/libarchive/archive_match.c
+++ b/Utilities/cmlibarchive/libarchive/archive_match.c
@@ -1582,7 +1582,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
*/
int
-archive_match_include_uid(struct archive *_a, int64_t uid)
+archive_match_include_uid(struct archive *_a, la_int64_t uid)
{
struct archive_match *a;
@@ -1593,7 +1593,7 @@ archive_match_include_uid(struct archive *_a, int64_t uid)
}
int
-archive_match_include_gid(struct archive *_a, int64_t gid)
+archive_match_include_gid(struct archive *_a, la_int64_t gid)
{
struct archive_match *a;
diff --git a/Utilities/cmlibarchive/libarchive/archive_pack_dev.c b/Utilities/cmlibarchive/libarchive/archive_pack_dev.c
index 098881b67..53bddd790 100644
--- a/Utilities/cmlibarchive/libarchive/archive_pack_dev.c
+++ b/Utilities/cmlibarchive/libarchive/archive_pack_dev.c
@@ -57,6 +57,9 @@ __RCSID("$NetBSD$");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_platform.h b/Utilities/cmlibarchive/libarchive/archive_platform.h
index f33208c9a..e161e6406 100644
--- a/Utilities/cmlibarchive/libarchive/archive_platform.h
+++ b/Utilities/cmlibarchive/libarchive/archive_platform.h
@@ -196,4 +196,10 @@
#define ARCHIVE_ERRNO_MISC (-1)
#endif
+#if defined(__GNUC__) && (__GNUC__ >= 7)
+#define __LA_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define __LA_FALLTHROUGH
+#endif
+
#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
index 1aed922db..d0bacc68c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
@@ -115,14 +115,14 @@ static void Ppmd7_Construct(CPpmd7 *p)
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
-static void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
+static void Ppmd7_Free(CPpmd7 *p)
{
- alloc->Free(alloc, p->Base);
+ free(p->Base);
p->Size = 0;
p->Base = 0;
}
-static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
+static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
{
if (p->Base == 0 || p->Size != size)
{
@@ -131,14 +131,14 @@ static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
if (size < UNIT_SIZE) {
return False;
}
- Ppmd7_Free(p, alloc);
+ Ppmd7_Free(p);
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
- if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
+ if ((p->Base = (Byte *)malloc(p->AlignOffset + size
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
index 06c99e828..577d6fb43 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
@@ -95,8 +95,8 @@ typedef struct
{
/* Base Functions */
void (*Ppmd7_Construct)(CPpmd7 *p);
- Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
- void (*Ppmd7_Free)(CPpmd7 *p, ISzAlloc *alloc);
+ Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size);
+ void (*Ppmd7_Free)(CPpmd7 *p);
void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
index e78bde594..a83b8514d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
@@ -69,13 +69,6 @@ typedef struct
void (*Write)(void *p, Byte b);
} IByteOut;
-
-typedef struct
-{
- void *(*Alloc)(void *p, size_t size);
- void (*Free)(void *p, void *address); /* address can be 0 */
-} ISzAlloc;
-
/*** End defined in Types.h ***/
/*** Begin defined in CpuArch.h ***/
diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c
index a642a336d..0e56e76e7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read.c
@@ -120,7 +120,8 @@ archive_read_new(void)
* Record the do-not-extract-to file. This belongs in archive_read_extract.c.
*/
void
-archive_read_extract_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d,
+ la_int64_t i)
{
struct archive_read *a = (struct archive_read *)_a;
@@ -747,7 +748,7 @@ choose_format(struct archive_read *a)
* Return the file offset (within the uncompressed data stream) where
* the last header started.
*/
-int64_t
+la_int64_t
archive_read_header_position(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
@@ -820,7 +821,7 @@ archive_read_format_capabilities(struct archive *_a)
* DO NOT intermingle calls to this function and archive_read_data_block
* to read a single entry body.
*/
-ssize_t
+la_ssize_t
archive_read_data(struct archive *_a, void *buff, size_t s)
{
struct archive *a = (struct archive *)_a;
@@ -943,7 +944,7 @@ archive_read_data_skip(struct archive *_a)
return (r);
}
-int64_t
+la_int64_t
archive_seek_data(struct archive *_a, int64_t offset, int whence)
{
struct archive_read *a = (struct archive_read *)_a;
@@ -1626,7 +1627,8 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
switch (whence) {
case SEEK_CUR:
/* Adjust the offset and use SEEK_SET instead */
- offset += filter->position;
+ offset += filter->position;
+ __LA_FALLTHROUGH;
case SEEK_SET:
cursor = 0;
while (1)
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
index 5e4d16307..da7c55b9b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
@@ -89,6 +89,10 @@ archive_read_append_filter(struct archive *_a, int code)
strcpy(str, "lz4");
r1 = archive_read_support_filter_lz4(_a);
break;
+ case ARCHIVE_FILTER_ZSTD:
+ strcpy(str, "zstd");
+ r1 = archive_read_support_filter_zstd(_a);
+ break;
case ARCHIVE_FILTER_LZIP:
strcpy(str, "lzip");
r1 = archive_read_support_filter_lzip(_a);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
index 548ba89ef..1786cff38 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
@@ -127,7 +127,7 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
/*
* Enter working directory and return working pathname of archive_entry.
* If a pointer to an integer is provided and its value is below zero
- * open a file descriptor on this pahtname.
+ * open a file descriptor on this pathname.
*/
const char *
archive_read_disk_entry_setup_path(struct archive_read_disk *a,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
index 6961ae6a4..cdf754123 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
@@ -387,7 +387,7 @@ archive_read_disk_vtable(void)
}
const char *
-archive_read_disk_gname(struct archive *_a, int64_t gid)
+archive_read_disk_gname(struct archive *_a, la_int64_t gid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -399,7 +399,7 @@ archive_read_disk_gname(struct archive *_a, int64_t gid)
}
const char *
-archive_read_disk_uname(struct archive *_a, int64_t uid)
+archive_read_disk_uname(struct archive *_a, la_int64_t uid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -413,7 +413,7 @@ archive_read_disk_uname(struct archive *_a, int64_t uid)
int
archive_read_disk_set_gname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_gname)(void *private, int64_t gid),
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
void (*cleanup_gname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
@@ -432,7 +432,7 @@ archive_read_disk_set_gname_lookup(struct archive *_a,
int
archive_read_disk_set_uname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_uname)(void *private, int64_t uid),
+ const char * (*lookup_uname)(void *private, la_int64_t uid),
void (*cleanup_uname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
index 3b903304f..d82048de2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
@@ -117,7 +117,7 @@ struct filesystem {
*/
#define MAX_OVERLAPPED 8
-#define BUFFER_SIZE (1024 * 8)
+#define READ_BUFFER_SIZE (1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */
#define DIRECT_IO 0/* Disabled */
#define ASYNC_IO 1/* Enabled */
@@ -320,7 +320,7 @@ archive_read_disk_vtable(void)
}
const char *
-archive_read_disk_gname(struct archive *_a, int64_t gid)
+archive_read_disk_gname(struct archive *_a, la_int64_t gid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -332,7 +332,7 @@ archive_read_disk_gname(struct archive *_a, int64_t gid)
}
const char *
-archive_read_disk_uname(struct archive *_a, int64_t uid)
+archive_read_disk_uname(struct archive *_a, la_int64_t uid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
@@ -346,7 +346,7 @@ archive_read_disk_uname(struct archive *_a, int64_t uid)
int
archive_read_disk_set_gname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_gname)(void *private, int64_t gid),
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
void (*cleanup_gname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
@@ -567,7 +567,7 @@ start_next_async_read(struct archive_read_disk *a, struct tree *t)
/* Allocate read buffer. */
if (olp->buff == NULL) {
void *p;
- size_t s = (size_t)align_num_per_sector(t, BUFFER_SIZE);
+ size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE);
p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
@@ -683,7 +683,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
break;
} while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
} else {
- if (start_next_async_read(a, t) == ARCHIVE_FATAL)
+ if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL)
goto abort_read_data;
}
@@ -923,6 +923,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
t->entry_fh = CreateFileW(tree_current_access_path(t),
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
"Couldn't open %ls", tree_current_path(a->tree));
return (ARCHIVE_FAILED);
@@ -2275,10 +2276,10 @@ setup_sparse_from_disk(struct archive_read_disk *a,
if (range.Length.QuadPart > 0)
continue;
} else {
- /* The remaining data is hole. */
+ /* The entire file is a hole. Add one data block of size 0 at the end. */
archive_entry_sparse_add_entry(entry,
- range.FileOffset.QuadPart,
- range.Length.QuadPart);
+ entry_size,
+ 0);
}
break;
} else {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_filter.3 b/Utilities/cmlibarchive/libarchive/archive_read_filter.3
index 7f020e373..ef0a70175 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_filter.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_filter.3
@@ -38,6 +38,7 @@
.Nm archive_read_support_filter_rpm ,
.Nm archive_read_support_filter_uu ,
.Nm archive_read_support_filter_xz ,
+.Nm archive_read_support_filter_zstd ,
.Nm archive_read_support_filter_program ,
.Nm archive_read_support_filter_program_signature
.Nd functions for reading streaming archives
@@ -73,6 +74,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_read_support_filter_xz "struct archive *"
.Ft int
+.Fn archive_read_support_filter_zstd "struct archive *"
+.Ft int
.Fo archive_read_support_filter_program
.Fa "struct archive *"
.Fa "const char *cmd"
@@ -99,7 +102,8 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_read_support_filter_none ,
.Fn archive_read_support_filter_rpm ,
.Fn archive_read_support_filter_uu ,
-.Fn archive_read_support_filter_xz
+.Fn archive_read_support_filter_xz ,
+.Fn archive_read_support_filter_zstd ,
.Xc
Enables auto-detection code and decompression support for the
specified compression.
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c
index 68c53de41..edb508c1d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c
@@ -71,6 +71,8 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_grzip(a);
/* Lz4 falls back to "lz4 -d" command-line program. */
archive_read_support_filter_lz4(a);
+ /* Zstd falls back to "zstd -d" command-line program. */
+ archive_read_support_filter_zstd(a);
/* Note: We always return ARCHIVE_OK here, even if some of the
* above return ARCHIVE_WARN. The intent here is to enable
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c
new file mode 100644
index 000000000..c8bb36be7
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 2009-2011 Sean Purcell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
+#include "archive.h"
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+
+struct private_data {
+ ZSTD_DStream *dstream;
+ unsigned char *out_block;
+ size_t out_block_size;
+ int64_t total_out;
+ char in_frame; /* True = in the middle of a zstd frame. */
+ char eof; /* True = found end of compressed data. */
+};
+
+/* Zstd Filter. */
+static ssize_t zstd_filter_read(struct archive_read_filter *, const void**);
+static int zstd_filter_close(struct archive_read_filter *);
+#endif
+
+/*
+ * Note that we can detect zstd compressed files even if we can't decompress
+ * them. (In fact, we like detecting them because we can give better error
+ * messages.) So the bid framework here gets compiled even if no zstd library
+ * is available.
+ */
+static int zstd_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int zstd_bidder_init(struct archive_read_filter *);
+
+int
+archive_read_support_filter_zstd(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *bidder;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_zstd");
+
+ if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ bidder->data = NULL;
+ bidder->name = "zstd";
+ bidder->bid = zstd_bidder_bid;
+ bidder->init = zstd_bidder_init;
+ bidder->options = NULL;
+ bidder->free = NULL;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return (ARCHIVE_OK);
+#else
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external zstd program for zstd decompression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+/*
+ * Test whether we can handle this data.
+ */
+static int
+zstd_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *buffer;
+ ssize_t avail;
+ unsigned prefix;
+
+ /* Zstd frame magic values */
+ const unsigned zstd_magic = 0xFD2FB528U;
+
+ (void) self; /* UNUSED */
+
+ buffer = __archive_read_filter_ahead(filter, 4, &avail);
+ if (buffer == NULL)
+ return (0);
+
+ prefix = archive_le32dec(buffer);
+ if (prefix == zstd_magic)
+ return (32);
+
+ return (0);
+}
+
+#if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
+
+/*
+ * If we don't have the library on this system, we can't do the
+ * decompression directly. We can, however, try to run "zstd -d"
+ * in case that's available.
+ */
+static int
+zstd_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "zstd -d -qq");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_ZSTD;
+ self->name = "zstd";
+ return (r);
+}
+
+#else
+
+/*
+ * Initialize the filter object
+ */
+static int
+zstd_bidder_init(struct archive_read_filter *self)
+{
+ struct private_data *state;
+ const size_t out_block_size = ZSTD_DStreamOutSize();
+ void *out_block;
+ ZSTD_DStream *dstream;
+
+ self->code = ARCHIVE_FILTER_ZSTD;
+ self->name = "zstd";
+
+ state = (struct private_data *)calloc(sizeof(*state), 1);
+ out_block = (unsigned char *)malloc(out_block_size);
+ dstream = ZSTD_createDStream();
+
+ if (state == NULL || out_block == NULL || dstream == NULL) {
+ free(out_block);
+ free(state);
+ ZSTD_freeDStream(dstream); /* supports free on NULL */
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for zstd decompression");
+ return (ARCHIVE_FATAL);
+ }
+
+ self->data = state;
+
+ state->out_block_size = out_block_size;
+ state->out_block = out_block;
+ state->dstream = dstream;
+ self->read = zstd_filter_read;
+ self->skip = NULL; /* not supported */
+ self->close = zstd_filter_close;
+
+ state->eof = 0;
+ state->in_frame = 0;
+
+ return (ARCHIVE_OK);
+}
+
+static ssize_t
+zstd_filter_read(struct archive_read_filter *self, const void **p)
+{
+ struct private_data *state;
+ size_t decompressed;
+ ssize_t avail_in;
+ ZSTD_outBuffer out;
+ ZSTD_inBuffer in;
+
+ state = (struct private_data *)self->data;
+
+ out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
+
+ /* Try to fill the output buffer. */
+ while (out.pos < out.size && !state->eof) {
+ if (!state->in_frame) {
+ const size_t ret = ZSTD_initDStream(state->dstream);
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Error initializing zstd decompressor: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+ }
+ in.src = __archive_read_filter_ahead(self->upstream, 1,
+ &avail_in);
+ if (avail_in < 0) {
+ return avail_in;
+ }
+ if (in.src == NULL && avail_in == 0) {
+ if (!state->in_frame) {
+ /* end of stream */
+ state->eof = 1;
+ break;
+ } else {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Truncated zstd input");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ in.size = avail_in;
+ in.pos = 0;
+
+ {
+ const size_t ret =
+ ZSTD_decompressStream(state->dstream, &out, &in);
+
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Zstd decompression failed: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Decompressor made some progress */
+ __archive_read_filter_consume(self->upstream, in.pos);
+
+ /* ret guaranteed to be > 0 if frame isn't done yet */
+ state->in_frame = (ret != 0);
+ }
+ }
+
+ decompressed = out.pos;
+ state->total_out += decompressed;
+ if (decompressed == 0)
+ *p = NULL;
+ else
+ *p = state->out_block;
+ return (decompressed);
+}
+
+/*
+ * Clean up the decompressor.
+ */
+static int
+zstd_filter_close(struct archive_read_filter *self)
+{
+ struct private_data *state;
+
+ state = (struct private_data *)self->data;
+
+ ZSTD_freeDStream(state->dstream);
+ free(state->out_block);
+ free(state);
+
+ return (ARCHIVE_OK);
+}
+
+#endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
index 96774f4e3..a885a4c45 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
@@ -975,18 +975,6 @@ decode_codec_id(const unsigned char *codecId, size_t id_size)
return (id);
}
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
static Byte
ppmd_read(void *p)
{
@@ -1006,8 +994,6 @@ ppmd_read(void *p)
return (b);
}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
-
static int
init_decompression(struct archive_read *a, struct _7zip *zip,
const struct _7z_coder *coder1, const struct _7z_coder *coder2)
@@ -1237,7 +1223,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
if (zip->ppmd7_valid) {
__archive_ppmd7_functions.Ppmd7_Free(
- &zip->ppmd7_context, &g_szalloc);
+ &zip->ppmd7_context);
zip->ppmd7_valid = 0;
}
@@ -1256,7 +1242,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
}
__archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context);
r = __archive_ppmd7_functions.Ppmd7_Alloc(
- &zip->ppmd7_context, msize, &g_szalloc);
+ &zip->ppmd7_context, msize);
if (r == 0) {
archive_set_error(&a->archive, ENOMEM,
"Coludn't allocate memory for PPMd");
@@ -1636,7 +1622,7 @@ free_decompression(struct archive_read *a, struct _7zip *zip)
#endif
if (zip->ppmd7_valid) {
__archive_ppmd7_functions.Ppmd7_Free(
- &zip->ppmd7_context, &g_szalloc);
+ &zip->ppmd7_context);
zip->ppmd7_valid = 0;
}
return (r);
@@ -2569,6 +2555,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
case kDummy:
if (ll == 0)
break;
+ __LA_FALLTHROUGH;
default:
if (header_bytes(a, ll) == NULL)
return (-1);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
index ad9f782de..67d5b21ee 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
@@ -633,6 +633,13 @@ header_newc(struct archive_read *a, struct cpio *cpio,
/* Pad name to 2 more than a multiple of 4. */
*name_pad = (2 - *namelength) & 3;
+ /* Make sure that the padded name length fits into size_t. */
+ if (*name_pad > SIZE_MAX - *namelength) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "cpio archive has invalid namelength");
+ return (ARCHIVE_FATAL);
+ }
+
/*
* Note: entry_bytes_remaining is at least 64 bits and
* therefore guaranteed to be big enough for a 33-bit file
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
index 4b436d1c4..93649f862 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
@@ -409,7 +409,8 @@ static int next_entry_seek(struct archive_read *, struct iso9660 *,
struct file_info **);
static struct file_info *
parse_file_info(struct archive_read *a,
- struct file_info *parent, const unsigned char *isodirrec);
+ struct file_info *parent, const unsigned char *isodirrec,
+ size_t reclen);
static int parse_rockridge(struct archive_read *a,
struct file_info *file, const unsigned char *start,
const unsigned char *end);
@@ -1022,7 +1023,7 @@ read_children(struct archive_read *a, struct file_info *parent)
if (*(p + DR_name_len_offset) == 1
&& *(p + DR_name_offset) == '\001')
continue;
- child = parse_file_info(a, parent, p);
+ child = parse_file_info(a, parent, p, b - p);
if (child == NULL) {
__archive_read_consume(a, skip_size);
return (ARCHIVE_FATAL);
@@ -1112,7 +1113,7 @@ choose_volume(struct archive_read *a, struct iso9660 *iso9660)
*/
seenJoliet = iso9660->seenJoliet;/* Save flag. */
iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
+ file = parse_file_info(a, NULL, block, vd->size);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
@@ -1144,7 +1145,7 @@ choose_volume(struct archive_read *a, struct iso9660 *iso9660)
return (ARCHIVE_FATAL);
}
iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
+ file = parse_file_info(a, NULL, block, vd->size);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
@@ -1749,7 +1750,7 @@ archive_read_format_iso9660_cleanup(struct archive_read *a)
*/
static struct file_info *
parse_file_info(struct archive_read *a, struct file_info *parent,
- const unsigned char *isodirrec)
+ const unsigned char *isodirrec, size_t reclen)
{
struct iso9660 *iso9660;
struct file_info *file, *filep;
@@ -1763,16 +1764,20 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
iso9660 = (struct iso9660 *)(a->format->data);
- dr_len = (size_t)isodirrec[DR_length_offset];
- name_len = (size_t)isodirrec[DR_name_len_offset];
- location = archive_le32dec(isodirrec + DR_extent_offset);
- fsize = toi(isodirrec + DR_size_offset, DR_size_size);
- /* Sanity check that dr_len needs at least 34. */
- if (dr_len < 34) {
+ if (reclen != 0)
+ dr_len = (size_t)isodirrec[DR_length_offset];
+ /*
+ * Sanity check that reclen is not zero and dr_len is greater than
+ * reclen but at least 34
+ */
+ if (reclen == 0 || reclen < dr_len || dr_len < 34) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Invalid length of directory record");
+ "Invalid length of directory record");
return (NULL);
}
+ name_len = (size_t)isodirrec[DR_name_len_offset];
+ location = archive_le32dec(isodirrec + DR_extent_offset);
+ fsize = toi(isodirrec + DR_size_offset, DR_size_size);
/* Sanity check that name_len doesn't exceed dr_len. */
if (dr_len - 33 < name_len || name_len == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
index 1995e9c66..98d02c62d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
@@ -701,6 +701,12 @@ archive_read_format_lha_read_header(struct archive_read *a,
* Prepare variables used to read a file content.
*/
lha->entry_bytes_remaining = lha->compsize;
+ if (lha->entry_bytes_remaining < 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid LHa entry size");
+ return (ARCHIVE_FATAL);
+ }
lha->entry_offset = 0;
lha->entry_crc_calculated = 0;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
index 44b6083cb..5b0eadc08 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
+#include "archive_rb.h"
#include "archive_read_private.h"
#include "archive_string.h"
#include "archive_pack_dev.h"
@@ -75,7 +76,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_OPTIONAL 0x0800
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
-#define MTREE_HASHTABLE_SIZE 1024
+#define MAX_LINE_LEN (1024 * 1024)
struct mtree_option {
struct mtree_option *next;
@@ -83,13 +84,13 @@ struct mtree_option {
};
struct mtree_entry {
+ struct archive_rb_node rbnode;
+ struct mtree_entry *next_dup;
struct mtree_entry *next;
struct mtree_option *options;
char *name;
char full;
char used;
- unsigned int name_hash;
- struct mtree_entry *hashtable_next;
};
struct mtree {
@@ -102,11 +103,12 @@ struct mtree {
const char *archive_format_name;
struct mtree_entry *entries;
struct mtree_entry *this_entry;
- struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
+ struct archive_rb_tree entry_rbtree;
struct archive_string current_dir;
struct archive_string contents_name;
struct archive_entry_linkresolver *resolver;
+ struct archive_rb_tree rbtree;
int64_t cur_size;
char checkfs;
@@ -115,7 +117,6 @@ struct mtree {
static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
static int detect_form(struct archive_read *, int *);
-static unsigned int hash(const char *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@@ -217,9 +218,30 @@ free_options(struct mtree_option *head)
}
}
+static int
+mtree_cmp_node(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
+ const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
+
+ return (strcmp(e1->name, e2->name));
+}
+
+static int
+mtree_cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ const struct mtree_entry *e = (const struct mtree_entry *)n;
+
+ return (strcmp(e->name, key));
+}
+
int
archive_read_support_format_mtree(struct archive *_a)
{
+ static const struct archive_rb_tree_ops rb_ops = {
+ mtree_cmp_node, mtree_cmp_key,
+ };
struct archive_read *a = (struct archive_read *)_a;
struct mtree *mtree;
int r;
@@ -235,6 +257,8 @@ archive_read_support_format_mtree(struct archive *_a)
}
mtree->fd = -1;
+ __archive_rb_tree_init(&mtree->rbtree, &rb_ops);
+
r = __archive_read_register_format(a, mtree, "mtree",
mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
@@ -334,6 +358,14 @@ next_line(struct archive_read *a,
size_t nbytes_req = (*ravail+1023) & ~1023U;
ssize_t tested;
+ /*
+ * Place an arbitrary limit on the line length.
+ * mtree is almost free-form input and without line length limits,
+ * it can consume a lot of memory.
+ */
+ if (len >= MAX_LINE_LEN)
+ return (-1);
+
/* Increase reading bytes if it is not enough to at least
* new two lines. */
if (nbytes_req < (size_t)*ravail + 160)
@@ -865,12 +897,11 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_option **global, const char *line, ssize_t line_len,
struct mtree_entry **last_entry, int is_form_d)
{
- struct mtree_entry *entry, *ht_iter;
+ struct mtree_entry *entry;
struct mtree_option *iter;
const char *next, *eq, *name, *end;
size_t name_len, len;
int r, i;
- unsigned int ht_idx;
if ((entry = malloc(sizeof(*entry))) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
@@ -881,8 +912,6 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
entry->name = NULL;
entry->used = 0;
entry->full = 0;
- entry->name_hash = 0;
- entry->hashtable_next = NULL;
/* Add this entry to list. */
if (*last_entry == NULL)
@@ -935,15 +964,17 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
memcpy(entry->name, name, name_len);
entry->name[name_len] = '\0';
parse_escapes(entry->name, entry);
- entry->name_hash = hash(entry->name);
- ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
- if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
- while (ht_iter->hashtable_next)
- ht_iter = ht_iter->hashtable_next;
- ht_iter->hashtable_next = entry;
- } else {
- mtree->entry_hashtable[ht_idx] = entry;
+ entry->next_dup = NULL;
+ if (entry->full) {
+ if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
+ struct mtree_entry *alt;
+ alt = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &mtree->rbtree, entry->name);
+ while (alt->next_dup)
+ alt = alt->next_dup;
+ alt->next_dup = entry;
+ }
}
for (iter = *global; iter != NULL; iter = iter->next) {
@@ -1138,14 +1169,13 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* with pathname canonicalization, which is a very
* tricky subject.)
*/
- for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
- if (mp->full && !mp->used
- && mentry->name_hash == mp->name_hash
- && strcmp(mentry->name, mp->name) == 0) {
+ mp = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &mtree->rbtree, mentry->name);
+ for (; mp; mp = mp->next_dup) {
+ if (mp->full && !mp->used) {
/* Later lines override earlier ones. */
mp->used = 1;
- r1 = parse_line(a, entry, mtree, mp,
- &parsed_kws);
+ r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
if (r1 < r)
r = r1;
}
@@ -1489,6 +1519,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
if (strcmp(key, "cksum") == 0)
break;
+ __LA_FALLTHROUGH;
case 'd':
if (strcmp(key, "device") == 0) {
/* stat(2) st_rdev field, e.g. the major/minor IDs
@@ -1502,12 +1533,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_rdev(entry, dev);
return r;
}
+ __LA_FALLTHROUGH;
case 'f':
if (strcmp(key, "flags") == 0) {
*parsed_kws |= MTREE_HAS_FFLAGS;
archive_entry_copy_fflags_text(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'g':
if (strcmp(key, "gid") == 0) {
*parsed_kws |= MTREE_HAS_GID;
@@ -1519,16 +1552,19 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_copy_gname(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 'l':
if (strcmp(key, "link") == 0) {
archive_entry_copy_symlink(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'm':
if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
break;
@@ -1545,6 +1581,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
break;
}
+ __LA_FALLTHROUGH;
case 'n':
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
@@ -1552,6 +1589,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
(unsigned int)mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 'r':
if (strcmp(key, "resdevice") == 0) {
/* stat(2) st_dev field, e.g. the device ID where the
@@ -1567,6 +1605,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0)
break;
+ __LA_FALLTHROUGH;
case 's':
if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
break;
@@ -1583,6 +1622,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_size(entry, mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 't':
if (strcmp(key, "tags") == 0) {
/*
@@ -1625,18 +1665,21 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_filetype(entry, AE_IFBLK);
break;
}
+ __LA_FALLTHROUGH;
case 'c':
if (strcmp(val, "char") == 0) {
archive_entry_set_filetype(entry,
AE_IFCHR);
break;
}
+ __LA_FALLTHROUGH;
case 'd':
if (strcmp(val, "dir") == 0) {
archive_entry_set_filetype(entry,
AE_IFDIR);
break;
}
+ __LA_FALLTHROUGH;
case 'f':
if (strcmp(val, "fifo") == 0) {
archive_entry_set_filetype(entry,
@@ -1648,12 +1691,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
AE_IFREG);
break;
}
+ __LA_FALLTHROUGH;
case 'l':
if (strcmp(val, "link") == 0) {
archive_entry_set_filetype(entry,
AE_IFLNK);
break;
}
+ __LA_FALLTHROUGH;
default:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -1665,6 +1710,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
*parsed_kws |= MTREE_HAS_TYPE;
break;
}
+ __LA_FALLTHROUGH;
case 'u':
if (strcmp(key, "uid") == 0) {
*parsed_kws |= MTREE_HAS_UID;
@@ -1676,6 +1722,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_copy_uname(entry, val);
break;
}
+ __LA_FALLTHROUGH;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unrecognized key %s=%s", key, val);
@@ -1962,19 +2009,3 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
find_off = u - mtree->line.s;
}
}
-
-static unsigned int
-hash(const char *p)
-{
- /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
- as used by ELF for hashing function names. */
- unsigned g, h = 0;
- while (*p != '\0') {
- h = (h << 4) + *p++;
- if ((g = h & 0xF0000000) != 0) {
- h ^= g >> 24;
- h &= 0x0FFFFFFF;
- }
- }
- return h;
-}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
index a0e641e35..c68d77b49 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
@@ -604,20 +604,6 @@ lzss_emit_match(struct rar *rar, int offset, int length)
rar->lzss.position += length;
}
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
-
static Byte
ppmd_read(void *p)
{
@@ -1038,7 +1024,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
case COMPRESS_METHOD_BEST:
ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
break;
default:
@@ -1253,7 +1239,7 @@ archive_read_format_rar_cleanup(struct archive_read *a)
free(rar->dbo);
free(rar->unp_buffer);
free(rar->lzss.window);
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
free(rar);
(a->format->data) = NULL;
return (ARCHIVE_OK);
@@ -1496,7 +1482,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
filename[filename_size++] = '\0';
- filename[filename_size++] = '\0';
+ /*
+ * Do not increment filename_size here as the computations below
+ * add the space for the terminating NUL explicitly.
+ */
+ filename[filename_size] = '\0';
/* Decoded unicode form is UTF-16BE, so we have to update a string
* conversion object for it. */
@@ -1654,7 +1644,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->unp_offset = 0;
rar->unp_buffer_size = UNP_BUFFER_SIZE;
memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->ppmd_valid = rar->ppmd_eod = 0;
/* Don't set any archive entries for non-file header types */
@@ -2118,7 +2108,7 @@ parse_codes(struct archive_read *a)
/* Make sure ppmd7_contest is freed before Ppmd7_Construct
* because reading a broken file cause this abnormal sequence. */
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->bytein.a = a;
rar->bytein.Read = &ppmd_read;
@@ -2133,7 +2123,7 @@ parse_codes(struct archive_read *a)
}
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
- rar->dictionary_size, &g_szalloc))
+ rar->dictionary_size))
{
archive_set_error(&a->archive, ENOMEM,
"Out of memory");
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
index 30d5bc83c..60800bb81 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
@@ -251,15 +251,15 @@ archive_read_support_format_tar(struct archive *_a)
ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
tar = (struct tar *)calloc(1, sizeof(*tar));
-#ifdef HAVE_COPYFILE_H
- /* Set this by default on Mac OS. */
- tar->process_mac_extensions = 1;
-#endif
if (tar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
+#ifdef HAVE_COPYFILE_H
+ /* Set this by default on Mac OS. */
+ tar->process_mac_extensions = 1;
+#endif
r = __archive_read_register_format(a, tar, "tar",
archive_read_format_tar_bid,
@@ -2241,7 +2241,7 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
else
tar->sparse_list = p;
tar->sparse_last = p;
- if (remaining < 0 || offset < 0) {
+ if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
return (ARCHIVE_FATAL);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
index eeac1c888..9292ed784 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
@@ -1040,6 +1040,9 @@ atol10(const char *p, size_t char_cnt)
uint64_t l;
int digit;
+ if (char_cnt == 0)
+ return (0);
+
l = 0;
digit = *p - '0';
while (digit >= 0 && digit < 10 && char_cnt-- > 0) {
@@ -1054,7 +1057,10 @@ atol8(const char *p, size_t char_cnt)
{
int64_t l;
int digit;
-
+
+ if (char_cnt == 0)
+ return (0);
+
l = 0;
while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7')
@@ -2623,6 +2629,14 @@ strappend_base64(struct xar *xar,
archive_strncat(as, (const char *)buff, len);
}
+static int
+is_string(const char *known, const char *data, size_t len)
+{
+ if (strlen(known) != len)
+ return -1;
+ return memcmp(data, known, len);
+}
+
static void
xml_data(void *userData, const char *s, int len)
{
@@ -2674,26 +2688,26 @@ xml_data(void *userData, const char *s, int len)
archive_strncpy(&(xar->file->symlink), s, len);
break;
case FILE_TYPE:
- if (strncmp("file", s, len) == 0 ||
- strncmp("hardlink", s, len) == 0)
+ if (is_string("file", s, len) == 0 ||
+ is_string("hardlink", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFREG;
- if (strncmp("directory", s, len) == 0)
+ if (is_string("directory", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFDIR;
- if (strncmp("symlink", s, len) == 0)
+ if (is_string("symlink", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFLNK;
- if (strncmp("character special", s, len) == 0)
+ if (is_string("character special", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFCHR;
- if (strncmp("block special", s, len) == 0)
+ if (is_string("block special", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFBLK;
- if (strncmp("socket", s, len) == 0)
+ if (is_string("socket", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFSOCK;
- if (strncmp("fifo", s, len) == 0)
+ if (is_string("fifo", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFIFO;
xar->file->has |= HAS_TYPE;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
index ddd445833..7e99b1275 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
@@ -511,7 +511,13 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
case 0x5455:
{
/* Extended time field "UT". */
- int flags = p[offset];
+ int flags;
+ if (datasize == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Incomplete extended time field");
+ return ARCHIVE_FAILED;
+ }
+ flags = p[offset];
offset++;
datasize--;
/* Flag bits indicate which dates are present. */
@@ -723,6 +729,11 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
case 0x9901:
/* WinZip AES extra data field. */
+ if (datasize < 6) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Incomplete AES field");
+ return ARCHIVE_FAILED;
+ }
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
/* Vendor version. */
zip_entry->aes_extra.vendor =
@@ -881,6 +892,24 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_entry->mode |= 0664;
}
+ /* Windows archivers sometimes use backslash as the directory separator.
+ Normalize to slash. */
+ if (zip_entry->system == 0 &&
+ (wp = archive_entry_pathname_w(entry)) != NULL) {
+ if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
+ size_t i;
+ struct archive_wstring s;
+ archive_string_init(&s);
+ archive_wstrcpy(&s, wp);
+ for (i = 0; i < archive_strlen(&s); i++) {
+ if (s.s[i] == '\\')
+ s.s[i] = '/';
+ }
+ archive_entry_copy_pathname_w(entry, s.s);
+ archive_wstring_free(&s);
+ }
+ }
+
/* Make sure that entries with a trailing '/' are marked as directories
* even if the External File Attributes contains bogus values. If this
* is not a directory and there is no type, assume regularfile. */
@@ -1056,6 +1085,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip->end_of_entry = 1;
/* Set up a more descriptive format name. */
+ archive_string_empty(&zip->format_name);
archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)",
version / 10, version % 10,
compression_name(zip->entry->compression));
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c
index 5ae09b626..554533ecb 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.c
+++ b/Utilities/cmlibarchive/libarchive/archive_string.c
@@ -214,7 +214,8 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
{
if (archive_wstring_ensure(as, as->length + s + 1) == NULL)
return (NULL);
- wmemmove(as->s + as->length, p, s);
+ if (s)
+ wmemmove(as->s + as->length, p, s);
as->length += s;
as->s[as->length] = 0;
return (as);
diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c
index 1e36ad7ee..e5c6e3bff 100644
--- a/Utilities/cmlibarchive/libarchive/archive_util.c
+++ b/Utilities/cmlibarchive/libarchive/archive_util.c
@@ -140,7 +140,7 @@ archive_compression_name(struct archive *a)
/*
* Return a count of the number of compressed bytes processed.
*/
-int64_t
+la_int64_t
archive_position_compressed(struct archive *a)
{
return archive_filter_bytes(a, -1);
@@ -149,7 +149,7 @@ archive_position_compressed(struct archive *a)
/*
* Return a count of the number of uncompressed bytes processed.
*/
-int64_t
+la_int64_t
archive_position_uncompressed(struct archive *a)
{
return archive_filter_bytes(a, 0);
diff --git a/Utilities/cmlibarchive/libarchive/archive_version_details.c b/Utilities/cmlibarchive/libarchive/archive_version_details.c
index 9289bf1ac..e773e5e45 100644
--- a/Utilities/cmlibarchive/libarchive/archive_version_details.c
+++ b/Utilities/cmlibarchive/libarchive/archive_version_details.c
@@ -45,6 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#ifdef HAVE_LZ4_H
#include <lz4.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_private.h"
@@ -59,6 +62,7 @@ archive_version_details(void)
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
+ const char *libzstd = archive_libzstd_version();
if (!init) {
archive_string_init(&str);
@@ -84,6 +88,10 @@ archive_version_details(void)
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
+ if (libzstd) {
+ archive_strcat(&str, " libzstd/");
+ archive_strcat(&str, libzstd);
+ }
}
return str.s;
}
@@ -131,3 +139,13 @@ archive_liblz4_version(void)
return NULL;
#endif
}
+
+const char *
+archive_libzstd_version(void)
+{
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return ZSTD_VERSION_STRING;
+#else
+ return NULL;
+#endif
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_virtual.c b/Utilities/cmlibarchive/libarchive/archive_virtual.c
index de2595a9e..f509ee5c6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_virtual.c
+++ b/Utilities/cmlibarchive/libarchive/archive_virtual.c
@@ -48,7 +48,7 @@ archive_filter_name(struct archive *a, int n)
return ((a->vtable->archive_filter_name)(a, n));
}
-int64_t
+la_int64_t
archive_filter_bytes(struct archive *a, int n)
{
return ((a->vtable->archive_filter_bytes)(a, n));
@@ -124,14 +124,15 @@ archive_write_finish_entry(struct archive *a)
return ((a->vtable->archive_write_finish_entry)(a));
}
-ssize_t
+la_ssize_t
archive_write_data(struct archive *a, const void *buff, size_t s)
{
return ((a->vtable->archive_write_data)(a, buff, s));
}
-ssize_t
-archive_write_data_block(struct archive *a, const void *buff, size_t s, int64_t o)
+la_ssize_t
+archive_write_data_block(struct archive *a, const void *buff, size_t s,
+ la_int64_t o)
{
if (a->vtable->archive_write_data_block == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
@@ -156,7 +157,7 @@ archive_read_next_header2(struct archive *a, struct archive_entry *entry)
int
archive_read_data_block(struct archive *a,
- const void **buff, size_t *s, int64_t *o)
+ const void **buff, size_t *s, la_int64_t *o)
{
return ((a->vtable->archive_read_data_block)(a, buff, s, o));
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.3 b/Utilities/cmlibarchive/libarchive/archive_write.3
index 376d71dee..c1164f5b5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write.3
@@ -71,7 +71,7 @@ support.
.\"
.Ss Set options
See
-.Xr archive_read_set_options 3 .
+.Xr archive_write_set_options 3 .
.\"
.Ss Open archive
See
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c
index 0634a2296..e8daf530d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write.c
@@ -190,7 +190,7 @@ archive_write_get_bytes_in_last_block(struct archive *_a)
* an archive to itself recursively.
*/
int
-archive_write_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write *a = (struct archive_write *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c
index 08f518ade..203f4142b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c
@@ -53,6 +53,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
{ ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
+ { ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd },
{ -1, NULL }
};
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c
index 85a8d4753..ffa633c96 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c
@@ -57,6 +57,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "lzop", archive_write_add_filter_lzop },
{ "uuencode", archive_write_add_filter_uuencode },
{ "xz", archive_write_add_filter_xz },
+ { "zstd", archive_write_add_filter_zstd },
{ NULL, NULL }
};
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
index bbcc1789a..986123ad8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
@@ -226,7 +226,12 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->compressed[7] = (uint8_t)(t>>24)&0xff;
} else
memset(&data->compressed[4], 0, 4);
- data->compressed[8] = 0; /* No deflate options */
+ if (data->compression_level == 9)
+ data->compressed[8] = 2;
+ else if(data->compression_level == 1)
+ data->compressed[8] = 4;
+ else
+ data->compressed[8] = 0;
data->compressed[9] = 3; /* OS=Unix */
data->stream.next_out += 10;
data->stream.avail_out -= 10;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c
new file mode 100644
index 000000000..671fc6aff
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2017 Sean Purcell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+/* Don't compile this if we don't have zstd.h */
+
+struct private_data {
+ int compression_level;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_CStream *cstream;
+ int64_t total_in;
+ ZSTD_outBuffer out;
+#else
+ struct archive_write_program_data *pdata;
+#endif
+};
+
+static int archive_compressor_zstd_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_compressor_zstd_open(struct archive_write_filter *);
+static int archive_compressor_zstd_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_compressor_zstd_close(struct archive_write_filter *);
+static int archive_compressor_zstd_free(struct archive_write_filter *);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+static int drive_compressor(struct archive_write_filter *,
+ struct private_data *, int, const void *, size_t);
+#endif
+
+
+/*
+ * Add a zstd compression filter to this write handle.
+ */
+int
+archive_write_add_filter_zstd(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct private_data *data;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ f->data = data;
+ f->open = &archive_compressor_zstd_open;
+ f->options = &archive_compressor_zstd_options;
+ f->close = &archive_compressor_zstd_close;
+ f->free = &archive_compressor_zstd_free;
+ f->code = ARCHIVE_FILTER_ZSTD;
+ f->name = "zstd";
+ data->compression_level = 3; /* Default level used by the zstd CLI */
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ data->cstream = ZSTD_createCStream();
+ if (data->cstream == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM,
+ "Failed to allocate zstd compressor object");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate("zstd");
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external zstd program");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+archive_compressor_zstd_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_freeCStream(data->cstream);
+ free(data->out.dst);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ f->data = NULL;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ int level = atoi(value);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ if (level < 1 || level > ZSTD_maxCLevel()) {
+#else
+ /* If we don't have the library, hard-code the max level */
+ if (level < 1 || level > 22) {
+#endif
+ return (ARCHIVE_WARN);
+ }
+ data->compression_level = level;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+/*
+ * Setup callback.
+ */
+static int
+archive_compressor_zstd_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (data->out.dst == NULL) {
+ size_t bs = ZSTD_CStreamOutSize(), bpb;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of
+ * the of bytes per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ data->out.size = bs;
+ data->out.pos = 0;
+ data->out.dst
+ = (unsigned char *)malloc(data->out.size);
+ if (data->out.dst == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+
+ f->write = archive_compressor_zstd_write;
+
+ if (ZSTD_isError(ZSTD_initCStream(data->cstream,
+ data->compression_level))) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Internal error initializing zstd compressor object");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Write data to the compressed stream.
+ */
+static int
+archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int ret;
+
+ /* Update statistics */
+ data->total_in += length;
+
+ if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK)
+ return (ret);
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Finish the compression...
+ */
+static int
+archive_compressor_zstd_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int r1, r2;
+
+ /* Finish zstd frame */
+ r1 = drive_compressor(f, data, 1, NULL, 0);
+
+ r2 = __archive_write_close_filter(f->next_filter);
+
+ return r1 < r2 ? r1 : r2;
+}
+
+/*
+ * Utility function to push input data through compressor,
+ * writing full output blocks as necessary.
+ *
+ * Note that this handles both the regular write case (finishing ==
+ * false) and the end-of-archive case (finishing == true).
+ */
+static int
+drive_compressor(struct archive_write_filter *f,
+ struct private_data *data, int finishing, const void *src, size_t length)
+{
+ ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 };
+
+ for (;;) {
+ if (data->out.pos == data->out.size) {
+ const int ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.size);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ data->out.pos = 0;
+ }
+
+ /* If there's nothing to do, we're done. */
+ if (!finishing && in.pos == in.size)
+ return (ARCHIVE_OK);
+
+ {
+ const size_t zstdret = !finishing ?
+ ZSTD_compressStream(data->cstream, &data->out, &in)
+ : ZSTD_endStream(data->cstream, &data->out);
+
+ if (ZSTD_isError(zstdret)) {
+ archive_set_error(f->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Zstd compression failed: %s",
+ ZSTD_getErrorName(zstdret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* If we're finishing, 0 means nothing left to flush */
+ if (finishing && zstdret == 0) {
+ const int ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.pos);
+ return (ret);
+ }
+ }
+ }
+}
+
+#else /* HAVE_ZSTD_H && HAVE_LIBZSTD */
+
+static int
+archive_compressor_zstd_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_string_sprintf(&as, "zstd -%d", data->compression_level);
+
+ f->write = archive_compressor_zstd_write;
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_zstd_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
index 4a42a3beb..affa50381 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
@@ -835,7 +835,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
int
-archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1786,7 +1786,7 @@ finish_metadata:
int
archive_write_disk_set_group_lookup(struct archive *_a,
void *private_data,
- int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
void (*cleanup_gid)(void *private))
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
@@ -1822,7 +1822,7 @@ archive_write_disk_set_user_lookup(struct archive *_a,
}
int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1833,7 +1833,7 @@ archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
}
int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1981,6 +1981,10 @@ restore_entry(struct archive_write_disk *a)
if ((en == EISDIR || en == EEXIST)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
+ if (S_ISDIR(a->mode)) {
+ /* Don't overwrite any settings on existing directories. */
+ a->todo = 0;
+ }
archive_entry_unset_size(a->entry);
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
index 94b016edf..78eda4abc 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
@@ -906,7 +906,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
int
-archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1156,7 +1156,7 @@ _archive_write_disk_finish_entry(struct archive *_a)
int
archive_write_disk_set_group_lookup(struct archive *_a,
void *private_data,
- int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
void (*cleanup_gid)(void *private))
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
@@ -1192,7 +1192,7 @@ archive_write_disk_set_user_lookup(struct archive *_a,
}
int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1203,7 +1203,7 @@ archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
}
int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -1322,9 +1322,20 @@ restore_entry(struct archive_write_disk *a)
}
}
+ if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
+ archive_set_error(&a->archive, en,
+ "Hard-link target '%s' does not exist.",
+ archive_entry_hardlink(a->entry));
+ return (ARCHIVE_FAILED);
+ }
+
if ((en == EISDIR || en == EEXIST)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
+ if (S_ISDIR(a->mode)) {
+ /* Don't overwrite any settings on existing directories. */
+ a->todo = 0;
+ }
archive_entry_unset_size(a->entry);
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_filter.3 b/Utilities/cmlibarchive/libarchive/archive_write_filter.3
index e1d189150..d6fa07131 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_filter.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_filter.3
@@ -42,7 +42,8 @@
.Nm archive_write_add_filter_none ,
.Nm archive_write_add_filter_program ,
.Nm archive_write_add_filter_uuencode ,
-.Nm archive_write_add_filter_xz
+.Nm archive_write_add_filter_xz ,
+.Nm archive_write_add_filter_zstd ,
.Nd functions enabling output filters
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -76,6 +77,8 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_uuencode "struct archive *"
.Ft int
.Fn archive_write_add_filter_xz "struct archive *"
+.Ft int
+.Fn archive_write_add_filter_zstd "struct archive *"
.Sh DESCRIPTION
.Bl -tag -width indent
.It Xo
@@ -89,6 +92,7 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_lzma ,
.Fn archive_write_add_filter_lzop ,
.Fn archive_write_add_filter_xz ,
+.Fn archive_write_add_filter_zstd ,
.Xc
The resulting archive will be compressed as specified.
Note that the compressed output is always properly blocked.
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
index 3fc5a07d7..2bd4ec41f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
@@ -2095,19 +2095,6 @@ compression_init_encoder_lzma2(struct archive *a,
/*
* _7_PPMD compressor.
*/
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
static void
ppmd_write(void *p, Byte b)
{
@@ -2167,7 +2154,7 @@ compression_init_encoder_ppmd(struct archive *a,
archive_le32enc(props+1, msize);
__archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
r = __archive_ppmd7_functions.Ppmd7_Alloc(
- &strm->ppmd7_context, msize, &g_szalloc);
+ &strm->ppmd7_context, msize);
if (r == 0) {
free(strm->buff);
free(strm);
@@ -2243,7 +2230,7 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
(void)a; /* UNUSED */
strm = (struct ppmd_stream *)lastrm->real_stream;
- __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
free(strm->buff);
free(strm);
lastrm->real_stream = NULL;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
index c9771d81a..50305ccbe 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
@@ -180,7 +180,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
}
memset(buff, ' ', 60);
- strncpy(&buff[AR_fmag_offset], "`\n", 2);
+ memcpy(&buff[AR_fmag_offset], "`\n", 2);
if (strcmp(pathname, "/") == 0 ) {
/* Entry is archive symbol table in GNU format */
@@ -189,7 +189,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
}
if (strcmp(pathname, "__.SYMDEF") == 0) {
/* Entry is archive symbol table in BSD format */
- strncpy(buff + AR_name_offset, "__.SYMDEF", 9);
+ memcpy(buff + AR_name_offset, "__.SYMDEF", 9);
goto stat;
}
if (strcmp(pathname, "//") == 0) {
@@ -225,7 +225,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* actually 15 bytes.
*/
if (strlen(filename) <= 15) {
- strncpy(&buff[AR_name_offset],
+ memcpy(&buff[AR_name_offset],
filename, strlen(filename));
buff[AR_name_offset + strlen(filename)] = '/';
} else {
@@ -248,7 +248,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
return (ARCHIVE_FATAL);
}
- strncpy(se, filename, strlen(filename));
+ memcpy(se, filename, strlen(filename));
strcpy(se + strlen(filename), "/\n");
ss = strstr(ar->strtab, se);
@@ -285,11 +285,11 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* archive header.
*/
if (strlen(filename) <= 16 && strchr(filename, ' ') == NULL) {
- strncpy(&buff[AR_name_offset], filename, strlen(filename));
+ memcpy(&buff[AR_name_offset], filename, strlen(filename));
buff[AR_name_offset + strlen(filename)] = ' ';
}
else {
- strncpy(buff + AR_name_offset, "#1/", 3);
+ memcpy(buff + AR_name_offset, "#1/", 3);
if (format_decimal(strlen(filename),
buff + AR_name_offset + 3,
AR_name_size - 3)) {
@@ -374,13 +374,14 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
return (ARCHIVE_WARN);
}
- ar->strtab = (char *)malloc(s);
+ ar->strtab = (char *)malloc(s + 1);
if (ar->strtab == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate strtab buffer");
return (ARCHIVE_FATAL);
}
- strncpy(ar->strtab, buff, s);
+ memcpy(ar->strtab, buff, s);
+ ar->strtab[s] = '\0';
ar->has_strtab = 1;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
index 0eaf733cd..3cebeae18 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
@@ -1654,7 +1654,7 @@ build_pax_attribute_name(char *dest, const char *src)
* GNU PAX Format 1.0 requires the special name, which pattern is:
* <dir>/GNUSparseFile.<pid>/<original file name>
*
- * Since reproducable archives are more important, use 0 as pid.
+ * Since reproducible archives are more important, use 0 as pid.
*
* This function is used for only Sparse file, a file type of which
* is regular file.
diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt
index bb3b8a71f..e9f88266d 100644
--- a/Utilities/cmliblzma/CMakeLists.txt
+++ b/Utilities/cmliblzma/CMakeLists.txt
@@ -6,22 +6,6 @@ include(CheckSymbolExists)
include(CheckTypeSize)
include(TestBigEndian)
-CHECK_C_SOURCE_COMPILES(
- "int test (void *restrict x);\nint main (void) {return 0;}"
- HAVE_RESTRICT)
-
-CHECK_C_SOURCE_COMPILES(
-"typedef struct abc *d;\nint test (d __restrict x);\nint main (void) {return 0;}"
- HAVE___RESTRICT)
-
-CHECK_C_SOURCE_COMPILES(
- "static inline int test (void) {return 0;}\nint main (void) {return test();}"
- HAVE_INLINE)
-
-CHECK_C_SOURCE_COMPILES (
- "static __inline int test (void) {return 0;}\nint main (void) {return test();}"
- HAVE___INLINE)
-
CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H)
CHECK_INCLUDE_FILE(inttypes.h HAVE_INTTYPES_H)
CHECK_INCLUDE_FILE(limits.h HAVE_LIMITS_H)
@@ -95,7 +79,7 @@ CHECK_TYPE_SIZE("unsigned short" SIZE_OF_UNSIGNED_SHORT)
CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED)
CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG)
CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG)
-CHECK_TYPE_SIZE("size_t" SIZE_OF_SIZE_T)
+CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
CHECK_TYPE_SIZE("__int64" __INT64)
CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64)
diff --git a/Utilities/cmliblzma/COPYING b/Utilities/cmliblzma/COPYING
index 43c90d059..20e60d5b2 100644
--- a/Utilities/cmliblzma/COPYING
+++ b/Utilities/cmliblzma/COPYING
@@ -47,7 +47,7 @@ XZ Utils Licensing
naturally it is not legally required. Here is an example of a good
notice to put into "about box" or into documentation:
- This software includes code from XZ Utils <http://tukaani.org/xz/>.
+ This software includes code from XZ Utils <https://tukaani.org/xz/>.
The following license texts are included in the following files:
- COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
diff --git a/Utilities/cmliblzma/common/common_w32res.rc b/Utilities/cmliblzma/common/common_w32res.rc
index fdb88d184..a70de3432 100644
--- a/Utilities/cmliblzma/common/common_w32res.rc
+++ b/Utilities/cmliblzma/common/common_w32res.rc
@@ -17,7 +17,7 @@
#define MY_VERSION LZMA_VERSION_MAJOR,LZMA_VERSION_MINOR,LZMA_VERSION_PATCH,MY_BUILD
#define MY_FILENAME MY_NAME MY_SUFFIX
-#define MY_COMPANY "The Tukaani Project <http://tukaani.org/>"
+#define MY_COMPANY "The Tukaani Project <https://tukaani.org/>"
#define MY_PRODUCT PACKAGE_NAME " <" PACKAGE_URL ">"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
diff --git a/Utilities/cmliblzma/common/sysdefs.h b/Utilities/cmliblzma/common/sysdefs.h
index a6edea8b0..22f487b9e 100644
--- a/Utilities/cmliblzma/common/sysdefs.h
+++ b/Utilities/cmliblzma/common/sysdefs.h
@@ -18,6 +18,7 @@
#if defined(_MSC_VER)
# pragma warning(push,1)
+# pragma warning(disable: 4028) /* formal parameter different from decl */
# pragma warning(disable: 4142) /* benign redefinition of type */
# pragma warning(disable: 4761) /* integral size mismatch in argument */
#endif
@@ -124,9 +125,9 @@
// The code currently assumes that size_t is either 32-bit or 64-bit.
#ifndef SIZE_MAX
-# if SIZE_OF_SIZE_T == 4
+# if SIZEOF_SIZE_T == 4
# define SIZE_MAX UINT32_MAX
-# elif SIZE_OF_SIZE_T == 8
+# elif SIZEOF_SIZE_T == 8
# define SIZE_MAX UINT64_MAX
# else
# error size_t is not 32-bit or 64-bit
@@ -175,6 +176,16 @@ typedef unsigned char _Bool;
# include <memory.h>
#endif
+// As of MSVC 2013, inline and restrict are supported with
+// non-standard keywords.
+#if defined(_WIN32) && defined(_MSC_VER)
+# ifndef inline
+# define inline __inline
+# endif
+# ifndef restrict
+# define restrict __restrict
+# endif
+#endif
////////////
// Macros //
diff --git a/Utilities/cmliblzma/common/tuklib_integer.h b/Utilities/cmliblzma/common/tuklib_integer.h
index 5e8262a11..5d8268580 100644
--- a/Utilities/cmliblzma/common/tuklib_integer.h
+++ b/Utilities/cmliblzma/common/tuklib_integer.h
@@ -106,6 +106,17 @@
#endif
+////////////////////////////////
+// Compiler-specific features //
+////////////////////////////////
+
+// Newer Intel C compilers require immintrin.h for _bit_scan_reverse()
+// and such functions.
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
+# include <immintrin.h>
+#endif
+
+
///////////////////
// Byte swapping //
///////////////////
@@ -329,8 +340,8 @@ unaligned_read32le(const uint8_t *buf)
static inline void
unaligned_write16be(uint8_t *buf, uint16_t num)
{
- buf[0] = num >> 8;
- buf[1] = num;
+ buf[0] = (uint8_t)(num >> 8);
+ buf[1] = (uint8_t)num;
return;
}
@@ -338,8 +349,8 @@ unaligned_write16be(uint8_t *buf, uint16_t num)
static inline void
unaligned_write16le(uint8_t *buf, uint16_t num)
{
- buf[0] = num;
- buf[1] = num >> 8;
+ buf[0] = (uint8_t)num;
+ buf[1] = (uint8_t)(num >> 8);
return;
}
@@ -347,10 +358,10 @@ unaligned_write16le(uint8_t *buf, uint16_t num)
static inline void
unaligned_write32be(uint8_t *buf, uint32_t num)
{
- buf[0] = num >> 24;
- buf[1] = num >> 16;
- buf[2] = num >> 8;
- buf[3] = num;
+ buf[0] = (uint8_t)(num >> 24);
+ buf[1] = (uint8_t)(num >> 16);
+ buf[2] = (uint8_t)(num >> 8);
+ buf[3] = (uint8_t)num;
return;
}
@@ -358,10 +369,10 @@ unaligned_write32be(uint8_t *buf, uint32_t num)
static inline void
unaligned_write32le(uint8_t *buf, uint32_t num)
{
- buf[0] = num;
- buf[1] = num >> 8;
- buf[2] = num >> 16;
- buf[3] = num >> 24;
+ buf[0] = (uint8_t)num;
+ buf[1] = (uint8_t)(num >> 8);
+ buf[2] = (uint8_t)(num >> 16);
+ buf[3] = (uint8_t)(num >> 24);
return;
}
diff --git a/Utilities/cmliblzma/config.h.in b/Utilities/cmliblzma/config.h.in
index 9c53150bf..06f7fcb37 100644
--- a/Utilities/cmliblzma/config.h.in
+++ b/Utilities/cmliblzma/config.h.in
@@ -29,7 +29,7 @@
@SIZE_OF_UNSIGNED_CODE@
@SIZE_OF_UNSIGNED_LONG_CODE@
@SIZE_OF_UNSIGNED_LONG_LONG_CODE@
-@SIZE_OF_SIZE_T_CODE@
+@SIZEOF_SIZE_T_CODE@
/*
* If we lack int64_t, define it to the first of __int64, int, long, and long long
@@ -180,32 +180,6 @@ typedef uint64_t uintmax_t;
#cmakedefine uintptr_t @uintptr_t@
-
-#cmakedefine HAVE_RESTRICT
-#cmakedefine HAVE___RESTRICT
-
-#cmakedefine HAVE_INLINE
-#cmakedefine HAVE___INLINE
-
-#ifndef HAVE_RESTRICT
-# ifdef HAVE___RESTRICT
-# define LZMA_RESTRICT __restrict
-# else
-# define LZMA_RESTRICT
-# endif
-#else
-# define LZMA_RESTRICT restrict
-#endif /* HAVE_RESTRICT */
-
-#ifndef HAVE_INLINE
-# ifdef HAVE___INLINE
-# define inline __inline
-# else
-# define inline
-# endif
-#endif /* HAVE_INLINE */
-
-
#cmakedefine WORDS_BIGENDIAN 1
#cmakedefine HAVE_BYTESWAP_H 1
diff --git a/Utilities/cmliblzma/liblzma/api/lzma.h b/Utilities/cmliblzma/liblzma/api/lzma.h
index fb874c3e1..aa88e4243 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma.h
@@ -82,12 +82,20 @@
# if !defined(UINT32_C) || !defined(UINT64_C) \
|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
/*
- * MSVC has no C99 support, and thus it cannot be used to
- * compile liblzma. The liblzma API has to still be usable
- * from MSVC, so we need to define the required standard
- * integer types here.
+ * MSVC versions older than 2013 have no C99 support, and
+ * thus they cannot be used to compile liblzma. Using an
+ * existing liblzma.dll with old MSVC can work though(*),
+ * but we need to define the required standard integer
+ * types here in a MSVC-specific way.
+ *
+ * (*) If you do this, the existing liblzma.dll probably uses
+ * a different runtime library than your MSVC-built
+ * application. Mixing runtimes is generally bad, but
+ * in this case it should work as long as you avoid
+ * the few rarely-needed liblzma functions that allocate
+ * memory and expect the caller to free it using free().
*/
-# if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
@@ -211,7 +219,11 @@
*/
#ifndef lzma_nothrow
# if defined(__cplusplus)
-# define lzma_nothrow throw()
+# if __cplusplus >= 201103L
+# define lzma_nothrow noexcept
+# else
+# define lzma_nothrow throw()
+# endif
# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
# define lzma_nothrow __attribute__((__nothrow__))
# else
@@ -286,7 +298,7 @@ extern "C" {
#include "lzma/filter.h"
#include "lzma/bcj.h"
#include "lzma/delta.h"
-#include "lzma/lzma.h"
+#include "lzma/lzma12.h"
/* Container formats */
#include "lzma/container.h"
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/base.h b/Utilities/cmliblzma/liblzma/api/lzma/base.h
index 43dde8d60..a6005accc 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/base.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/base.h
@@ -240,12 +240,12 @@ typedef enum {
/**
* \brief The `action' argument for lzma_code()
*
- * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH,
- * the same `action' must is used until lzma_code() returns LZMA_STREAM_END.
- * Also, the amount of input (that is, strm->avail_in) must not be modified
- * by the application until lzma_code() returns LZMA_STREAM_END. Changing the
- * `action' or modifying the amount of input will make lzma_code() return
- * LZMA_PROG_ERROR.
+ * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
+ * or LZMA_FINISH, the same `action' must is used until lzma_code() returns
+ * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
+ * not be modified by the application until lzma_code() returns
+ * LZMA_STREAM_END. Changing the `action' or modifying the amount of input
+ * will make lzma_code() return LZMA_PROG_ERROR.
*/
typedef enum {
LZMA_RUN = 0,
@@ -293,7 +293,7 @@ typedef enum {
*
* All the input data going to the current Block must have
* been given to the encoder (the last bytes can still be
- * pending in* next_in). Call lzma_code() with LZMA_FULL_FLUSH
+ * pending in *next_in). Call lzma_code() with LZMA_FULL_FLUSH
* until it returns LZMA_STREAM_END. Then continue normally
* with LZMA_RUN or finish the Stream with LZMA_FINISH.
*
@@ -302,6 +302,29 @@ typedef enum {
* no unfinished Block, no empty Block is created.
*/
+ LZMA_FULL_BARRIER = 4,
+ /**<
+ * \brief Finish encoding of the current Block
+ *
+ * This is like LZMA_FULL_FLUSH except that this doesn't
+ * necessarily wait until all the input has been made
+ * available via the output buffer. That is, lzma_code()
+ * might return LZMA_STREAM_END as soon as all the input
+ * has been consumed (avail_in == 0).
+ *
+ * LZMA_FULL_BARRIER is useful with a threaded encoder if
+ * one wants to split the .xz Stream into Blocks at specific
+ * offsets but doesn't care if the output isn't flushed
+ * immediately. Using LZMA_FULL_BARRIER allows keeping
+ * the threads busy while LZMA_FULL_FLUSH would make
+ * lzma_code() wait until all the threads have finished
+ * until more data could be passed to the encoder.
+ *
+ * With a lzma_stream initialized with the single-threaded
+ * lzma_stream_encoder() or lzma_easy_encoder(),
+ * LZMA_FULL_BARRIER is an alias for LZMA_FULL_FLUSH.
+ */
+
LZMA_FINISH = 3
/**<
* \brief Finish the coding operation
@@ -332,11 +355,19 @@ typedef enum {
* malloc() and free(). C++ users should note that the custom memory
* handling functions must not throw exceptions.
*
- * liblzma doesn't make an internal copy of lzma_allocator. Thus, it is
- * OK to change these function pointers in the middle of the coding
- * process, but obviously it must be done carefully to make sure that the
- * replacement `free' can deallocate memory allocated by the earlier
- * `alloc' function(s).
+ * Single-threaded mode only: liblzma doesn't make an internal copy of
+ * lzma_allocator. Thus, it is OK to change these function pointers in
+ * the middle of the coding process, but obviously it must be done
+ * carefully to make sure that the replacement `free' can deallocate
+ * memory allocated by the earlier `alloc' function(s).
+ *
+ * Multithreaded mode: liblzma might internally store pointers to the
+ * lzma_allocator given via the lzma_stream structure. The application
+ * must not change the allocator pointer in lzma_stream or the contents
+ * of the pointed lzma_allocator structure until lzma_end() has been used
+ * to free the memory associated with that lzma_stream. The allocation
+ * functions might be called simultaneously from multiple threads, and
+ * thus they must be thread safe.
*/
typedef struct {
/**
@@ -448,7 +479,8 @@ typedef struct lzma_internal_s lzma_internal;
*
* Application may modify the values of total_in and total_out as it wants.
* They are updated by liblzma to match the amount of data read and
- * written, but aren't used for anything else.
+ * written but aren't used for anything else except as a possible return
+ * values from lzma_get_progress().
*/
typedef struct {
const uint8_t *next_in; /**< Pointer to the next input byte. */
@@ -464,8 +496,10 @@ typedef struct {
*
* In most cases this is NULL which makes liblzma use
* the standard malloc() and free().
+ *
+ * \note In 5.0.x this is not a const pointer.
*/
- lzma_allocator *allocator;
+ const lzma_allocator *allocator;
/** Internal state is not visible to applications. */
lzma_internal *internal;
@@ -547,6 +581,25 @@ extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
/**
+ * \brief Get progress information
+ *
+ * In single-threaded mode, applications can get progress information from
+ * strm->total_in and strm->total_out. In multi-threaded mode this is less
+ * useful because a significant amount of both input and output data gets
+ * buffered internally by liblzma. This makes total_in and total_out give
+ * misleading information and also makes the progress indicator updates
+ * non-smooth.
+ *
+ * This function gives realistic progress information also in multi-threaded
+ * mode by taking into account the progress made by each thread. In
+ * single-threaded mode *progress_in and *progress_out are set to
+ * strm->total_in and strm->total_out, respectively.
+ */
+extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
+ uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
+
+
+/**
* \brief Get the memory usage of decoder filter chain
*
* This function is currently supported only when *strm has been initialized
@@ -591,11 +644,16 @@ extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
* This function is supported only when *strm has been initialized with
* a function that takes a memlimit argument.
*
+ * liblzma 5.2.3 and earlier has a bug where memlimit value of 0 causes
+ * this function to do nothing (leaving the limit unchanged) and still
+ * return LZMA_OK. Later versions treat 0 as if 1 had been specified (so
+ * lzma_memlimit_get() will return 1 even if you specify 0 here).
+ *
* \return - LZMA_OK: New memory usage limit successfully set.
* - LZMA_MEMLIMIT_ERROR: The new limit is too small.
* The limit was not changed.
* - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
- * support memory usage limit or memlimit was zero.
+ * support memory usage limit.
*/
extern LZMA_API(lzma_ret) lzma_memlimit_set(
lzma_stream *strm, uint64_t memlimit) lzma_nothrow;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/block.h b/Utilities/cmliblzma/liblzma/api/lzma/block.h
index e6710a7bc..7bdcfd7cb 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/block.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/block.h
@@ -31,11 +31,16 @@ typedef struct {
/**
* \brief Block format version
*
- * To prevent API and ABI breakages if new features are needed in
- * the Block field, a version number is used to indicate which
- * fields in this structure are in use. For now, version must always
- * be zero. With non-zero version, most Block related functions will
- * return LZMA_OPTIONS_ERROR.
+ * To prevent API and ABI breakages when new features are needed,
+ * a version number is used to indicate which fields in this
+ * structure are in use:
+ * - liblzma >= 5.0.0: version = 0 is supported.
+ * - liblzma >= 5.1.4beta: Support for version = 1 was added,
+ * which adds the ignore_check field.
+ *
+ * If version is greater than one, most Block related functions
+ * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
+ * with any version value).
*
* Read by:
* - All functions that take pointer to lzma_block as argument,
@@ -233,7 +238,28 @@ typedef struct {
lzma_reserved_enum reserved_enum2;
lzma_reserved_enum reserved_enum3;
lzma_reserved_enum reserved_enum4;
- lzma_bool reserved_bool1;
+
+ /**
+ * \brief A flag to Block decoder to not verify the Check field
+ *
+ * This field is supported by liblzma >= 5.1.4beta if .version >= 1.
+ *
+ * If this is set to true, the integrity check won't be calculated
+ * and verified. Unless you know what you are doing, you should
+ * leave this to false. (A reason to set this to true is when the
+ * file integrity is verified externally anyway and you want to
+ * speed up the decompression, which matters mostly when using
+ * SHA-256 as the integrity check.)
+ *
+ * If .version >= 1, read by:
+ * - lzma_block_decoder()
+ * - lzma_block_buffer_decode()
+ *
+ * Written by (.version is ignored):
+ * - lzma_block_header_decode() always sets this to false
+ */
+ lzma_bool ignore_check;
+
lzma_bool reserved_bool2;
lzma_bool reserved_bool3;
lzma_bool reserved_bool4;
@@ -310,10 +336,14 @@ extern LZMA_API(lzma_ret) lzma_block_header_encode(
/**
* \brief Decode Block Header
*
- * block->version should be set to the highest value supported by the
- * application; currently the only possible version is zero. This function
- * will set version to the lowest value that still supports all the features
- * required by the Block Header.
+ * block->version should (usually) be set to the highest value supported
+ * by the application. If the application sets block->version to a value
+ * higher than supported by the current liblzma version, this function will
+ * downgrade block->version to the highest value supported by it. Thus one
+ * should check the value of block->version after calling this function if
+ * block->version was set to a non-zero value and the application doesn't
+ * otherwise know that the liblzma version being used is new enough to
+ * support the specified block->version.
*
* The size of the Block Header must have already been decoded with
* lzma_block_header_size_decode() macro and stored to block->header_size.
@@ -344,7 +374,7 @@ extern LZMA_API(lzma_ret) lzma_block_header_encode(
* block->header_size is invalid or block->filters is NULL.
*/
extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
- lzma_allocator *allocator, const uint8_t *in)
+ const lzma_allocator *allocator, const uint8_t *in)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -493,7 +523,25 @@ extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
- lzma_block *block, lzma_allocator *allocator,
+ lzma_block *block, const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
+ lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief Single-call uncompressed .xz Block encoder
+ *
+ * This is like lzma_block_buffer_encode() except this doesn't try to
+ * compress the data and instead encodes the data using LZMA2 uncompressed
+ * chunks. The required output buffer size can be determined with
+ * lzma_block_buffer_bound().
+ *
+ * Since the data won't be compressed, this function ignores block->filters.
+ * This function doesn't take lzma_allocator because this function doesn't
+ * allocate any memory from the heap.
+ */
+extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -527,7 +575,7 @@ extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
- lzma_block *block, lzma_allocator *allocator,
+ lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/container.h b/Utilities/cmliblzma/liblzma/api/lzma/container.h
index 7a9ffc645..9fbf4df06 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/container.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/container.h
@@ -61,6 +61,131 @@
/**
+ * \brief Multithreading options
+ */
+typedef struct {
+ /**
+ * \brief Flags
+ *
+ * Set this to zero if no flags are wanted.
+ *
+ * No flags are currently supported.
+ */
+ uint32_t flags;
+
+ /**
+ * \brief Number of worker threads to use
+ */
+ uint32_t threads;
+
+ /**
+ * \brief Maximum uncompressed size of a Block
+ *
+ * The encoder will start a new .xz Block every block_size bytes.
+ * Using LZMA_FULL_FLUSH or LZMA_FULL_BARRIER with lzma_code()
+ * the caller may tell liblzma to start a new Block earlier.
+ *
+ * With LZMA2, a recommended block size is 2-4 times the LZMA2
+ * dictionary size. With very small dictionaries, it is recommended
+ * to use at least 1 MiB block size for good compression ratio, even
+ * if this is more than four times the dictionary size. Note that
+ * these are only recommendations for typical use cases; feel free
+ * to use other values. Just keep in mind that using a block size
+ * less than the LZMA2 dictionary size is waste of RAM.
+ *
+ * Set this to 0 to let liblzma choose the block size depending
+ * on the compression options. For LZMA2 it will be 3*dict_size
+ * or 1 MiB, whichever is more.
+ *
+ * For each thread, about 3 * block_size bytes of memory will be
+ * allocated. This may change in later liblzma versions. If so,
+ * the memory usage will probably be reduced, not increased.
+ */
+ uint64_t block_size;
+
+ /**
+ * \brief Timeout to allow lzma_code() to return early
+ *
+ * Multithreading can make liblzma to consume input and produce
+ * output in a very bursty way: it may first read a lot of input
+ * to fill internal buffers, then no input or output occurs for
+ * a while.
+ *
+ * In single-threaded mode, lzma_code() won't return until it has
+ * either consumed all the input or filled the output buffer. If
+ * this is done in multithreaded mode, it may cause a call
+ * lzma_code() to take even tens of seconds, which isn't acceptable
+ * in all applications.
+ *
+ * To avoid very long blocking times in lzma_code(), a timeout
+ * (in milliseconds) may be set here. If lzma_code() would block
+ * longer than this number of milliseconds, it will return with
+ * LZMA_OK. Reasonable values are 100 ms or more. The xz command
+ * line tool uses 300 ms.
+ *
+ * If long blocking times are fine for you, set timeout to a special
+ * value of 0, which will disable the timeout mechanism and will make
+ * lzma_code() block until all the input is consumed or the output
+ * buffer has been filled.
+ *
+ * \note Even with a timeout, lzma_code() might sometimes take
+ * somewhat long time to return. No timing guarantees
+ * are made.
+ */
+ uint32_t timeout;
+
+ /**
+ * \brief Compression preset (level and possible flags)
+ *
+ * The preset is set just like with lzma_easy_encoder().
+ * The preset is ignored if filters below is non-NULL.
+ */
+ uint32_t preset;
+
+ /**
+ * \brief Filter chain (alternative to a preset)
+ *
+ * If this is NULL, the preset above is used. Otherwise the preset
+ * is ignored and the filter chain specified here is used.
+ */
+ const lzma_filter *filters;
+
+ /**
+ * \brief Integrity check type
+ *
+ * See check.h for available checks. The xz command line tool
+ * defaults to LZMA_CHECK_CRC64, which is a good choice if you
+ * are unsure.
+ */
+ lzma_check check;
+
+ /*
+ * Reserved space to allow possible future extensions without
+ * breaking the ABI. You should not touch these, because the names
+ * of these variables may change. These are and will never be used
+ * with the currently supported options, so it is safe to leave these
+ * uninitialized.
+ */
+ lzma_reserved_enum reserved_enum1;
+ lzma_reserved_enum reserved_enum2;
+ lzma_reserved_enum reserved_enum3;
+ uint32_t reserved_int1;
+ uint32_t reserved_int2;
+ uint32_t reserved_int3;
+ uint32_t reserved_int4;
+ uint64_t reserved_int5;
+ uint64_t reserved_int6;
+ uint64_t reserved_int7;
+ uint64_t reserved_int8;
+ void *reserved_ptr1;
+ void *reserved_ptr2;
+ void *reserved_ptr3;
+ void *reserved_ptr4;
+
+} lzma_mt;
+
+
+/**
* \brief Calculate approximate memory usage of easy encoder
*
* This function is a wrapper for lzma_raw_encoder_memusage().
@@ -165,7 +290,8 @@ extern LZMA_API(lzma_ret) lzma_easy_encoder(
*/
extern LZMA_API(lzma_ret) lzma_easy_buffer_encode(
uint32_t preset, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+ const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
@@ -191,6 +317,49 @@ extern LZMA_API(lzma_ret) lzma_stream_encoder(lzma_stream *strm,
/**
+ * \brief Calculate approximate memory usage of multithreaded .xz encoder
+ *
+ * Since doing the encoding in threaded mode doesn't affect the memory
+ * requirements of single-threaded decompressor, you can use
+ * lzma_easy_decoder_memusage(options->preset) or
+ * lzma_raw_decoder_memusage(options->filters) to calculate
+ * the decompressor memory requirements.
+ *
+ * \param options Compression options
+ *
+ * \return Number of bytes of memory required for encoding with the
+ * given options. If an error occurs, for example due to
+ * unsupported preset or filter chain, UINT64_MAX is returned.
+ */
+extern LZMA_API(uint64_t) lzma_stream_encoder_mt_memusage(
+ const lzma_mt *options) lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief Initialize multithreaded .xz Stream encoder
+ *
+ * This provides the functionality of lzma_easy_encoder() and
+ * lzma_stream_encoder() as a single function for multithreaded use.
+ *
+ * The supported actions for lzma_code() are LZMA_RUN, LZMA_FULL_FLUSH,
+ * LZMA_FULL_BARRIER, and LZMA_FINISH. Support for LZMA_SYNC_FLUSH might be
+ * added in the future.
+ *
+ * \param strm Pointer to properly prepared lzma_stream
+ * \param options Pointer to multithreaded compression options
+ *
+ * \return - LZMA_OK
+ * - LZMA_MEM_ERROR
+ * - LZMA_UNSUPPORTED_CHECK
+ * - LZMA_OPTIONS_ERROR
+ * - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_encoder_mt(
+ lzma_stream *strm, const lzma_mt *options)
+ lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
* \brief Initialize .lzma encoder (legacy file format)
*
* The .lzma format is sometimes called the LZMA_Alone format, which is the
@@ -269,7 +438,8 @@ extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
*/
extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
lzma_filter *filters, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+ const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -305,6 +475,30 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
/**
+ * This flag makes lzma_code() not calculate and verify the integrity check
+ * of the compressed data in .xz files. This means that invalid integrity
+ * check values won't be detected and LZMA_DATA_ERROR won't be returned in
+ * such cases.
+ *
+ * This flag only affects the checks of the compressed data itself; the CRC32
+ * values in the .xz headers will still be verified normally.
+ *
+ * Don't use this flag unless you know what you are doing. Possible reasons
+ * to use this flag:
+ *
+ * - Trying to recover data from a corrupt .xz file.
+ *
+ * - Speeding up decompression, which matters mostly with SHA-256
+ * or with files that have compressed extremely well. It's recommended
+ * to not use this flag for this purpose unless the file integrity is
+ * verified externally in some other way.
+ *
+ * Support for this flag was added in liblzma 5.1.4beta.
+ */
+#define LZMA_IGNORE_CHECK UINT32_C(0x10)
+
+
+/**
* This flag enables decoding of concatenated files with file formats that
* allow concatenating compressed files as is. From the formats currently
* supported by liblzma, only the .xz format allows concatenated files.
@@ -326,7 +520,10 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
*
* \param strm Pointer to properly prepared lzma_stream
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
- * to effectively disable the limiter.
+ * to effectively disable the limiter. liblzma
+ * 5.2.3 and earlier don't allow 0 here and return
+ * LZMA_PROG_ERROR; later versions treat 0 as if 1
+ * had been specified.
* \param flags Bitwise-or of zero or more of the decoder flags:
* LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
* LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED
@@ -350,7 +547,10 @@ extern LZMA_API(lzma_ret) lzma_stream_decoder(
*
* \param strm Pointer to properly prepared lzma_stream
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
- * to effectively disable the limiter.
+ * to effectively disable the limiter. liblzma
+ * 5.2.3 and earlier don't allow 0 here and return
+ * LZMA_PROG_ERROR; later versions treat 0 as if 1
+ * had been specified.
* \param flags Bitwise-or of flags, or zero for no flags.
*
* \return - LZMA_OK: Initialization was successful.
@@ -366,9 +566,16 @@ extern LZMA_API(lzma_ret) lzma_auto_decoder(
/**
* \brief Initialize .lzma decoder (legacy file format)
*
+ * \param strm Pointer to properly prepared lzma_stream
+ * \param memlimit Memory usage limit as bytes. Use UINT64_MAX
+ * to effectively disable the limiter. liblzma
+ * 5.2.3 and earlier don't allow 0 here and return
+ * LZMA_PROG_ERROR; later versions treat 0 as if 1
+ * had been specified.
+ *
* Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
- * There is no need to use LZMA_FINISH, but allowing it may simplify
- * certain types of applications.
+ * There is no need to use LZMA_FINISH, but it's allowed because it may
+ * simplify certain types of applications.
*
* \return - LZMA_OK
* - LZMA_MEM_ERROR
@@ -418,7 +625,8 @@ extern LZMA_API(lzma_ret) lzma_alone_decoder(
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
- uint64_t *memlimit, uint32_t flags, lzma_allocator *allocator,
+ uint64_t *memlimit, uint32_t flags,
+ const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/filter.h b/Utilities/cmliblzma/liblzma/api/lzma/filter.h
index e0bc163ad..4e78752b8 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/filter.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/filter.h
@@ -116,8 +116,9 @@ extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
* is not NULL.
* - LZMA_PROG_ERROR: src or dest is NULL.
*/
-extern LZMA_API(lzma_ret) lzma_filters_copy(const lzma_filter *src,
- lzma_filter *dest, lzma_allocator *allocator) lzma_nothrow;
+extern LZMA_API(lzma_ret) lzma_filters_copy(
+ const lzma_filter *src, lzma_filter *dest,
+ const lzma_allocator *allocator) lzma_nothrow;
/**
@@ -256,7 +257,7 @@ extern LZMA_API(lzma_ret) lzma_filters_update(
* won't necessarily meet that bound.)
*/
extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
- const lzma_filter *filters, lzma_allocator *allocator,
+ const lzma_filter *filters, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size, uint8_t *out,
size_t *out_pos, size_t out_size) lzma_nothrow;
@@ -280,7 +281,7 @@ extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
* which no data is written to is out[out_size].
*/
extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
- const lzma_filter *filters, lzma_allocator *allocator,
+ const lzma_filter *filters, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
@@ -356,7 +357,7 @@ extern LZMA_API(lzma_ret) lzma_properties_encode(
* - LZMA_MEM_ERROR
*/
extern LZMA_API(lzma_ret) lzma_properties_decode(
- lzma_filter *filter, lzma_allocator *allocator,
+ lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size) lzma_nothrow;
@@ -419,6 +420,6 @@ extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filter,
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
- lzma_filter *filter, lzma_allocator *allocator,
+ lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/hardware.h b/Utilities/cmliblzma/liblzma/api/lzma/hardware.h
index e7dd03c3e..5321d9af8 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/hardware.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/hardware.h
@@ -48,3 +48,17 @@
* of RAM on the specific operating system.
*/
extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow;
+
+
+/**
+ * \brief Get the number of processor cores or threads
+ *
+ * This function may be useful when determining how many threads to use.
+ * If the hardware supports more than one thread per CPU core, the number
+ * of hardware threads is returned if that information is available.
+ *
+ * \brief On success, the number of available CPU threads or cores is
+ * returned. If this information isn't available or an error
+ * occurs, zero is returned.
+ */
+extern LZMA_API(uint32_t) lzma_cputhreads(void) lzma_nothrow;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/index.h b/Utilities/cmliblzma/liblzma/api/lzma/index.h
index 16bacc287..3dac6fb85 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/index.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/index.h
@@ -303,7 +303,7 @@ extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
* \return On success, a pointer to an empty initialized lzma_index is
* returned. If allocation fails, NULL is returned.
*/
-extern LZMA_API(lzma_index *) lzma_index_init(lzma_allocator *allocator)
+extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator)
lzma_nothrow;
@@ -312,8 +312,8 @@ extern LZMA_API(lzma_index *) lzma_index_init(lzma_allocator *allocator)
*
* If i is NULL, this does nothing.
*/
-extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator)
- lzma_nothrow;
+extern LZMA_API(void) lzma_index_end(
+ lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
/**
@@ -341,7 +341,7 @@ extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator)
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_index_append(
- lzma_index *i, lzma_allocator *allocator,
+ lzma_index *i, const lzma_allocator *allocator,
lzma_vli unpadded_size, lzma_vli uncompressed_size)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -564,8 +564,8 @@ extern LZMA_API(lzma_bool) lzma_index_iter_locate(
* - LZMA_MEM_ERROR
* - LZMA_PROG_ERROR
*/
-extern LZMA_API(lzma_ret) lzma_index_cat(
- lzma_index *dest, lzma_index *src, lzma_allocator *allocator)
+extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *dest, lzma_index *src,
+ const lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -575,7 +575,7 @@ extern LZMA_API(lzma_ret) lzma_index_cat(
* \return A copy of the lzma_index, or NULL if memory allocation failed.
*/
extern LZMA_API(lzma_index *) lzma_index_dup(
- const lzma_index *i, lzma_allocator *allocator)
+ const lzma_index *i, const lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -586,8 +586,7 @@ extern LZMA_API(lzma_index *) lzma_index_dup(
* \param i Pointer to lzma_index which should be encoded.
*
* The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
- * It is enough to use only one of them (you can choose freely; use LZMA_RUN
- * to support liblzma versions older than 5.0.0).
+ * It is enough to use only one of them (you can choose freely).
*
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
* - LZMA_MEM_ERROR
@@ -610,16 +609,21 @@ extern LZMA_API(lzma_ret) lzma_index_encoder(
* to a new lzma_index, which the application
* has to later free with lzma_index_end().
* \param memlimit How much memory the resulting lzma_index is
- * allowed to require.
+ * allowed to require. liblzma 5.2.3 and earlier
+ * don't allow 0 here and return LZMA_PROG_ERROR;
+ * later versions treat 0 as if 1 had been specified.
*
- * The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
- * It is enough to use only one of them (you can choose freely; use LZMA_RUN
- * to support liblzma versions older than 5.0.0).
+ * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * There is no need to use LZMA_FINISH, but it's allowed because it may
+ * simplify certain types of applications.
*
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
* - LZMA_MEM_ERROR
- * - LZMA_MEMLIMIT_ERROR
* - LZMA_PROG_ERROR
+ *
+ * liblzma 5.2.3 and older list also LZMA_MEMLIMIT_ERROR here
+ * but that error code has never been possible from this
+ * initialization function.
*/
extern LZMA_API(lzma_ret) lzma_index_decoder(
lzma_stream *strm, lzma_index **i, uint64_t memlimit)
@@ -677,6 +681,6 @@ extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
- uint64_t *memlimit, lzma_allocator *allocator,
+ uint64_t *memlimit, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
lzma_nothrow;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/index_hash.h b/Utilities/cmliblzma/liblzma/api/lzma/index_hash.h
index fa2e048d5..9287f1dfd 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/index_hash.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/index_hash.h
@@ -37,7 +37,7 @@ typedef struct lzma_index_hash_s lzma_index_hash;
* pointer than the index_hash that was given as an argument.
*/
extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
- lzma_index_hash *index_hash, lzma_allocator *allocator)
+ lzma_index_hash *index_hash, const lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
@@ -45,7 +45,7 @@ extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
* \brief Deallocate lzma_index_hash structure
*/
extern LZMA_API(void) lzma_index_hash_end(
- lzma_index_hash *index_hash, lzma_allocator *allocator)
+ lzma_index_hash *index_hash, const lzma_allocator *allocator)
lzma_nothrow;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/lzma.h b/Utilities/cmliblzma/liblzma/api/lzma/lzma12.h
index 3f8e095f7..4e32fa3a2 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/lzma.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/lzma12.h
@@ -1,5 +1,5 @@
/**
- * \file lzma/lzma.h
+ * \file lzma/lzma12.h
* \brief LZMA1 and LZMA2 filters
*/
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/version.h b/Utilities/cmliblzma/liblzma/api/lzma/version.h
index 09866b982..143c7dea6 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/version.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/version.h
@@ -21,8 +21,8 @@
* Version number split into components
*/
#define LZMA_VERSION_MAJOR 5
-#define LZMA_VERSION_MINOR 0
-#define LZMA_VERSION_PATCH 8
+#define LZMA_VERSION_MINOR 2
+#define LZMA_VERSION_PATCH 4
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
#ifndef LZMA_VERSION_COMMIT
diff --git a/Utilities/cmliblzma/liblzma/check/check.c b/Utilities/cmliblzma/liblzma/check/check.c
index 979b0a818..428ddaeb7 100644
--- a/Utilities/cmliblzma/liblzma/check/check.c
+++ b/Utilities/cmliblzma/liblzma/check/check.c
@@ -16,6 +16,9 @@
extern LZMA_API(lzma_bool)
lzma_check_is_supported(lzma_check type)
{
+ if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+ return false;
+
static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
true, // LZMA_CHECK_NONE
@@ -53,9 +56,6 @@ lzma_check_is_supported(lzma_check type)
false, // Reserved
};
- if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
- return false;
-
return available_checks[(unsigned int)(type)];
}
@@ -63,6 +63,9 @@ lzma_check_is_supported(lzma_check type)
extern LZMA_API(uint32_t)
lzma_check_size(lzma_check type)
{
+ if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+ return UINT32_MAX;
+
// See file-format.txt section 2.1.1.2.
static const uint8_t check_sizes[LZMA_CHECK_ID_MAX + 1] = {
0,
@@ -73,9 +76,6 @@ lzma_check_size(lzma_check type)
64, 64, 64
};
- if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
- return UINT32_MAX;
-
return check_sizes[(unsigned int)(type)];
}
diff --git a/Utilities/cmliblzma/liblzma/check/check.h b/Utilities/cmliblzma/liblzma/check/check.h
index e100d2b85..3007d889b 100644
--- a/Utilities/cmliblzma/liblzma/check/check.h
+++ b/Utilities/cmliblzma/liblzma/check/check.h
@@ -15,6 +15,53 @@
#include "common.h"
+// If the function for external SHA-256 is missing, use the internal SHA-256
+// code. Due to how configure works, these defines can only get defined when
+// both a usable header and a type have already been found.
+#if !(defined(HAVE_CC_SHA256_INIT) \
+ || defined(HAVE_SHA256_INIT) \
+ || defined(HAVE_SHA256INIT))
+# define HAVE_INTERNAL_SHA256 1
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+// Nothing
+#elif defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
+# include <CommonCrypto/CommonDigest.h>
+#elif defined(HAVE_SHA256_H)
+# include <sys/types.h>
+# include <sha256.h>
+#elif defined(HAVE_SHA2_H)
+# include <sys/types.h>
+# include <sha2.h>
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+/// State for the internal SHA-256 implementation
+typedef struct {
+ /// Internal state
+ uint32_t state[8];
+
+ /// Size of the message excluding padding
+ uint64_t size;
+} lzma_sha256_state;
+#elif defined(HAVE_CC_SHA256_CTX)
+typedef CC_SHA256_CTX lzma_sha256_state;
+#elif defined(HAVE_SHA256_CTX)
+typedef SHA256_CTX lzma_sha256_state;
+#elif defined(HAVE_SHA2_CTX)
+typedef SHA2_CTX lzma_sha256_state;
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+// Nothing
+#elif defined(HAVE_CC_SHA256_INIT)
+# define LZMA_SHA256FUNC(x) CC_SHA256_ ## x
+#elif defined(HAVE_SHA256_INIT)
+# define LZMA_SHA256FUNC(x) SHA256_ ## x
+#elif defined(HAVE_SHA256INIT)
+# define LZMA_SHA256FUNC(x) SHA256 ## x
+#endif
// Index hashing needs the best possible hash function (preferably
// a cryptographic hash) for maximum reliability.
@@ -43,14 +90,7 @@ typedef struct {
union {
uint32_t crc32;
uint64_t crc64;
-
- struct {
- /// Internal state
- uint32_t state[8];
-
- /// Size of the message excluding padding
- uint64_t size;
- } sha256;
+ lzma_sha256_state sha256;
} state;
} lzma_check_state;
@@ -82,6 +122,8 @@ extern void lzma_check_update(lzma_check_state *check, lzma_check type,
extern void lzma_check_finish(lzma_check_state *check, lzma_check type);
+#ifndef LZMA_SHA256FUNC
+
/// Prepare SHA-256 state for new input.
extern void lzma_sha256_init(lzma_check_state *check);
@@ -92,4 +134,39 @@ extern void lzma_sha256_update(
/// Finish the SHA-256 calculation and store the result to check->buffer.u8.
extern void lzma_sha256_finish(lzma_check_state *check);
+
+#else
+
+static inline void
+lzma_sha256_init(lzma_check_state *check)
+{
+ LZMA_SHA256FUNC(Init)(&check->state.sha256);
+}
+
+
+static inline void
+lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
+{
+#if defined(HAVE_CC_SHA256_INIT) && SIZE_MAX > UINT32_MAX
+ // Darwin's CC_SHA256_Update takes uint32_t as the buffer size,
+ // so use a loop to support size_t.
+ while (size > UINT32_MAX) {
+ LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, UINT32_MAX);
+ buf += UINT32_MAX;
+ size -= UINT32_MAX;
+ }
+#endif
+
+ LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, size);
+}
+
+
+static inline void
+lzma_sha256_finish(lzma_check_state *check)
+{
+ LZMA_SHA256FUNC(Final)(check->buffer.u8, &check->state.sha256);
+}
+
+#endif
+
#endif
diff --git a/Utilities/cmliblzma/liblzma/check/crc32_fast.c b/Utilities/cmliblzma/liblzma/check/crc32_fast.c
index c2c3cb79b..3de02638d 100644
--- a/Utilities/cmliblzma/liblzma/check/crc32_fast.c
+++ b/Utilities/cmliblzma/liblzma/check/crc32_fast.c
@@ -33,8 +33,6 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
#endif
if (size > 8) {
- const uint8_t * limit;
-
// Fix the alignment, if needed. The if statement above
// ensures that this won't read past the end of buf[].
while ((uintptr_t)(buf) & 7) {
@@ -43,7 +41,7 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
}
// Calculate the position where to stop.
- limit = buf + (size & ~(size_t)(7));
+ const uint8_t *const limit = buf + (size & ~(size_t)(7));
// Calculate how many bytes must be calculated separately
// before returning the result.
@@ -51,8 +49,6 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
// Calculate the CRC32 using the slice-by-eight algorithm.
while (buf < limit) {
- uint32_t tmp;
-
crc ^= *(const uint32_t *)(buf);
buf += 4;
@@ -61,7 +57,7 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
^ lzma_crc32_table[5][C(crc)]
^ lzma_crc32_table[4][D(crc)];
- tmp = *(const uint32_t *)(buf);
+ const uint32_t tmp = *(const uint32_t *)(buf);
buf += 4;
// At least with some compilers, it is critical for
diff --git a/Utilities/cmliblzma/liblzma/check/crc64_fast.c b/Utilities/cmliblzma/liblzma/check/crc64_fast.c
index 1436557af..52af29ed4 100644
--- a/Utilities/cmliblzma/liblzma/check/crc64_fast.c
+++ b/Utilities/cmliblzma/liblzma/check/crc64_fast.c
@@ -36,14 +36,12 @@ lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
#endif
if (size > 4) {
- const uint8_t *limit;
-
while ((uintptr_t)(buf) & 3) {
crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
--size;
}
- limit = buf + (size & ~(size_t)(3));
+ const uint8_t *const limit = buf + (size & ~(size_t)(3));
size &= (size_t)(3);
while (buf < limit) {
diff --git a/Utilities/cmliblzma/liblzma/check/sha256.c b/Utilities/cmliblzma/liblzma/check/sha256.c
index 3af6aa67d..5eede5ce0 100644
--- a/Utilities/cmliblzma/liblzma/check/sha256.c
+++ b/Utilities/cmliblzma/liblzma/check/sha256.c
@@ -21,22 +21,22 @@
//
///////////////////////////////////////////////////////////////////////////////
-// Avoid bogus warnings in transform().
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __GNUC__ > 4
-# pragma GCC diagnostic ignored "-Wuninitialized"
-#endif
-
#include "check.h"
-// At least on x86, GCC is able to optimize this to a rotate instruction.
-#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount)))
+// Rotate a uint32_t. GCC can optimize this to a rotate instruction
+// at least on x86.
+static inline uint32_t
+rotr_32(uint32_t num, unsigned amount)
+{
+ return (num >> amount) | (num << (32 - amount));
+}
-#define blk0(i) (W[i] = data[i])
+#define blk0(i) (W[i] = conv32be(data[i]))
#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
+ s0(W[(i - 15) & 15]))
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
-#define Maj(x, y, z) ((x & y) | (z & (x | y)))
+#define Maj(x, y, z) ((x & (y ^ z)) + (y & z))
#define a(i) T[(0 - i) & 7]
#define b(i) T[(1 - i) & 7]
@@ -47,16 +47,17 @@
#define g(i) T[(6 - i) & 7]
#define h(i) T[(7 - i) & 7]
-#define R(i) \
- h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \
- + (j ? blk2(i) : blk0(i)); \
+#define R(i, j, blk) \
+ h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] + blk; \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
+#define R0(i) R(i, 0, blk0(i))
+#define R2(i) R(i, j, blk2(i))
-#define S0(x) (rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22))
-#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25))
-#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3))
-#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10))
+#define S0(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 9), 11), 2)
+#define S1(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 14), 5), 6)
+#define s0(x) (rotr_32(x ^ rotr_32(x, 11), 7) ^ (x >> 3))
+#define s1(x) (rotr_32(x ^ rotr_32(x, 2), 17) ^ (x >> 10))
static const uint32_t SHA256_K[64] = {
@@ -84,17 +85,22 @@ transform(uint32_t state[8], const uint32_t data[16])
{
uint32_t W[16];
uint32_t T[8];
- unsigned int j;
// Copy state[] to working vars.
memcpy(T, state, sizeof(T));
- // 64 operations, partially loop unrolled
- for (j = 0; j < 64; j += 16) {
- R( 0); R( 1); R( 2); R( 3);
- R( 4); R( 5); R( 6); R( 7);
- R( 8); R( 9); R(10); R(11);
- R(12); R(13); R(14); R(15);
+ // The first 16 operations unrolled
+ R0( 0); R0( 1); R0( 2); R0( 3);
+ R0( 4); R0( 5); R0( 6); R0( 7);
+ R0( 8); R0( 9); R0(10); R0(11);
+ R0(12); R0(13); R0(14); R0(15);
+
+ // The remaining 48 operations partially unrolled
+ for (unsigned int j = 16; j < 64; j += 16) {
+ R2( 0); R2( 1); R2( 2); R2( 3);
+ R2( 4); R2( 5); R2( 6); R2( 7);
+ R2( 8); R2( 9); R2(10); R2(11);
+ R2(12); R2(13); R2(14); R2(15);
}
// Add the working vars back into state[].
@@ -112,19 +118,7 @@ transform(uint32_t state[8], const uint32_t data[16])
static void
process(lzma_check_state *check)
{
-#ifdef WORDS_BIGENDIAN
transform(check->state.sha256.state, check->buffer.u32);
-
-#else
- uint32_t data[16];
- size_t i;
-
- for (i = 0; i < 16; ++i)
- data[i] = bswap32(check->buffer.u32[i]);
-
- transform(check->state.sha256.state, data);
-#endif
-
return;
}
@@ -174,8 +168,6 @@ lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
extern void
lzma_sha256_finish(lzma_check_state *check)
{
- size_t i;
-
// Add padding as described in RFC 3174 (it describes SHA-1 but
// the same padding style is used for SHA-256 too).
size_t pos = check->state.sha256.size & 0x3F;
@@ -197,7 +189,7 @@ lzma_sha256_finish(lzma_check_state *check)
process(check);
- for (i = 0; i < 8; ++i)
+ for (size_t i = 0; i < 8; ++i)
check->buffer.u32[i] = conv32be(check->state.sha256.state[i]);
return;
diff --git a/Utilities/cmliblzma/liblzma/common/alone_decoder.c b/Utilities/cmliblzma/liblzma/common/alone_decoder.c
index 5f5e564ab..77d0a9b10 100644
--- a/Utilities/cmliblzma/liblzma/common/alone_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/alone_decoder.c
@@ -15,7 +15,7 @@
#include "lz_decoder.h"
-struct lzma_coder_s {
+typedef struct {
lzma_next_coder next;
enum {
@@ -46,17 +46,19 @@ struct lzma_coder_s {
/// Options decoded from the header needed to initialize
/// the LZMA decoder
lzma_options_lzma options;
-};
+} lzma_alone_coder;
static lzma_ret
-alone_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+alone_decode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action)
{
+ lzma_alone_coder *coder = coder_ptr;
+
while (*out_pos < out_size
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
switch (coder->sequence) {
@@ -126,17 +128,19 @@ alone_decode(lzma_coder *coder,
// Fall through
case SEQ_CODER_INIT: {
- lzma_ret ret;
+ if (coder->memusage > coder->memlimit)
+ return LZMA_MEMLIMIT_ERROR;
lzma_filter_info filters[2] = {
- { 0, &lzma_lzma_decoder_init, &coder->options },
- { 0, NULL, NULL }
+ {
+ .init = &lzma_lzma_decoder_init,
+ .options = &coder->options,
+ }, {
+ .init = NULL,
+ }
};
- if (coder->memusage > coder->memlimit)
- return LZMA_MEMLIMIT_ERROR;
-
- ret = lzma_next_filter_init(&coder->next,
+ const lzma_ret ret = lzma_next_filter_init(&coder->next,
allocator, filters);
if (ret != LZMA_OK)
return ret;
@@ -164,8 +168,9 @@ alone_decode(lzma_coder *coder,
static void
-alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+alone_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_alone_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
@@ -173,9 +178,11 @@ alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+alone_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_alone_coder *coder = coder_ptr;
+
*memusage = coder->memusage;
*old_memlimit = coder->memlimit;
@@ -191,34 +198,34 @@ alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
extern lzma_ret
-lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_alone_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, bool picky)
{
lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator);
- if (memlimit == 0)
- return LZMA_PROG_ERROR;
+ lzma_alone_coder *coder = next->coder;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &alone_decode;
next->end = &alone_decoder_end;
next->memconfig = &alone_decoder_memconfig;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
- next->coder->sequence = SEQ_PROPERTIES;
- next->coder->picky = picky;
- next->coder->pos = 0;
- next->coder->options.dict_size = 0;
- next->coder->options.preset_dict = NULL;
- next->coder->options.preset_dict_size = 0;
- next->coder->uncompressed_size = 0;
- next->coder->memlimit = memlimit;
- next->coder->memusage = LZMA_MEMUSAGE_BASE;
+ coder->sequence = SEQ_PROPERTIES;
+ coder->picky = picky;
+ coder->pos = 0;
+ coder->options.dict_size = 0;
+ coder->options.preset_dict = NULL;
+ coder->options.preset_dict_size = 0;
+ coder->uncompressed_size = 0;
+ coder->memlimit = my_max(1, memlimit);
+ coder->memusage = LZMA_MEMUSAGE_BASE;
return LZMA_OK;
}
@@ -227,7 +234,7 @@ lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
{
- lzma_next_strm_init2(lzma_alone_decoder_init, strm, memlimit, false);
+ lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit, false);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/Utilities/cmliblzma/liblzma/common/alone_decoder.h b/Utilities/cmliblzma/liblzma/common/alone_decoder.h
index f666fc382..dfa031aa7 100644
--- a/Utilities/cmliblzma/liblzma/common/alone_decoder.h
+++ b/Utilities/cmliblzma/liblzma/common/alone_decoder.h
@@ -17,7 +17,7 @@
extern lzma_ret lzma_alone_decoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, bool picky);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/alone_encoder.c b/Utilities/cmliblzma/liblzma/common/alone_encoder.c
index 4207b4a52..4853cfd1d 100644
--- a/Utilities/cmliblzma/liblzma/common/alone_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/alone_encoder.c
@@ -17,7 +17,7 @@
#define ALONE_HEADER_SIZE (1 + 4 + 8)
-struct lzma_coder_s {
+typedef struct {
lzma_next_coder next;
enum {
@@ -27,17 +27,19 @@ struct lzma_coder_s {
size_t header_pos;
uint8_t header[ALONE_HEADER_SIZE];
-};
+} lzma_alone_coder;
static lzma_ret
-alone_encode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+alone_encode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action)
{
+ lzma_alone_coder *coder = coder_ptr;
+
while (*out_pos < out_size)
switch (coder->sequence) {
case SEQ_HEADER:
@@ -65,8 +67,9 @@ alone_encode(lzma_coder *coder,
static void
-alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_alone_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
@@ -75,36 +78,31 @@ alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
// At least for now, this is not used by any internal function.
static lzma_ret
-alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_options_lzma *options)
{
- uint32_t d;
-
- // Initialize the LZMA encoder.
- const lzma_filter_info filters[2] = {
- { 0, &lzma_lzma_encoder_init, (void *)(options) },
- { 0, NULL, NULL }
- };
-
lzma_next_coder_init(&alone_encoder_init, next, allocator);
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_alone_coder *coder = next->coder;
+
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &alone_encode;
next->end = &alone_encoder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Basic initializations
- next->coder->sequence = SEQ_HEADER;
- next->coder->header_pos = 0;
+ coder->sequence = SEQ_HEADER;
+ coder->header_pos = 0;
// Encode the header:
// - Properties (1 byte)
- if (lzma_lzma_lclppb_encode(options, next->coder->header))
+ if (lzma_lzma_lclppb_encode(options, coder->header))
return LZMA_OPTIONS_ERROR;
// - Dictionary size (4 bytes)
@@ -115,7 +113,7 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// one is the next unless it is UINT32_MAX. While the header would
// allow any 32-bit integer, we do this to keep the decoder of liblzma
// accepting the resulting files.
- d = options->dict_size - 1;
+ uint32_t d = options->dict_size - 1;
d |= d >> 2;
d |= d >> 3;
d |= d >> 4;
@@ -124,18 +122,28 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
if (d != UINT32_MAX)
++d;
- unaligned_write32le(next->coder->header + 1, d);
+ unaligned_write32le(coder->header + 1, d);
// - Uncompressed size (always unknown and using EOPM)
- memset(next->coder->header + 1 + 4, 0xFF, 8);
+ memset(coder->header + 1 + 4, 0xFF, 8);
+
+ // Initialize the LZMA encoder.
+ const lzma_filter_info filters[2] = {
+ {
+ .init = &lzma_lzma_encoder_init,
+ .options = (void *)(options),
+ }, {
+ .init = NULL,
+ }
+ };
- return lzma_next_filter_init(&next->coder->next, allocator, filters);
+ return lzma_next_filter_init(&coder->next, allocator, filters);
}
/*
extern lzma_ret
-lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_options_alone *options)
{
lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
@@ -146,7 +154,7 @@ lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
{
- lzma_next_strm_init1(alone_encoder_init, strm, options);
+ lzma_next_strm_init(alone_encoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/Utilities/cmliblzma/liblzma/common/auto_decoder.c b/Utilities/cmliblzma/liblzma/common/auto_decoder.c
index 24cf48905..6895c7ccf 100644
--- a/Utilities/cmliblzma/liblzma/common/auto_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/auto_decoder.c
@@ -14,7 +14,7 @@
#include "alone_decoder.h"
-struct lzma_coder_s {
+typedef struct {
/// Stream decoder or LZMA_Alone decoder
lzma_next_coder next;
@@ -26,15 +26,17 @@ struct lzma_coder_s {
SEQ_CODE,
SEQ_FINISH,
} sequence;
-};
+} lzma_auto_coder;
static lzma_ret
-auto_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+auto_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_auto_coder *coder = coder_ptr;
+
switch (coder->sequence) {
case SEQ_INIT:
if (*in_pos >= in_size)
@@ -100,8 +102,9 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
-auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+auto_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_auto_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
@@ -109,8 +112,10 @@ auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_check
-auto_decoder_get_check(const lzma_coder *coder)
+auto_decoder_get_check(const void *coder_ptr)
{
+ const lzma_auto_coder *coder = coder_ptr;
+
// It is LZMA_Alone if get_check is NULL.
return coder->next.get_check == NULL ? LZMA_CHECK_NONE
: coder->next.get_check(coder->next.coder);
@@ -118,9 +123,11 @@ auto_decoder_get_check(const lzma_coder *coder)
static lzma_ret
-auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+auto_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_auto_coder *coder = coder_ptr;
+
lzma_ret ret;
if (coder->next.memconfig != NULL) {
@@ -132,7 +139,10 @@ auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
// the current memory usage.
*memusage = LZMA_MEMUSAGE_BASE;
*old_memlimit = coder->memlimit;
+
ret = LZMA_OK;
+ if (new_memlimit != 0 && new_memlimit < *memusage)
+ ret = LZMA_MEMLIMIT_ERROR;
}
if (ret == LZMA_OK && new_memlimit != 0)
@@ -143,32 +153,31 @@ auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
static lzma_ret
-auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+auto_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, uint32_t flags)
{
lzma_next_coder_init(&auto_decoder_init, next, allocator);
- if (memlimit == 0)
- return LZMA_PROG_ERROR;
-
if (flags & ~LZMA_SUPPORTED_FLAGS)
return LZMA_OPTIONS_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_auto_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_auto_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &auto_decode;
next->end = &auto_decoder_end;
next->get_check = &auto_decoder_get_check;
next->memconfig = &auto_decoder_memconfig;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
- next->coder->memlimit = memlimit;
- next->coder->flags = flags;
- next->coder->sequence = SEQ_INIT;
+ coder->memlimit = my_max(1, memlimit);
+ coder->flags = flags;
+ coder->sequence = SEQ_INIT;
return LZMA_OK;
}
@@ -177,7 +186,7 @@ auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{
- lzma_next_strm_init2(auto_decoder_init, strm, memlimit, flags);
+ lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c b/Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c
index b4bd388eb..b0ded90dd 100644
--- a/Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c
@@ -14,13 +14,10 @@
extern LZMA_API(lzma_ret)
-lzma_block_buffer_decode(lzma_block *block, lzma_allocator *allocator,
+lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder block_decoder;
- lzma_ret ret;
-
if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|| *in_pos > in_size || out_pos == NULL
|| (out == NULL && *out_pos != out_size)
@@ -28,8 +25,9 @@ lzma_block_buffer_decode(lzma_block *block, lzma_allocator *allocator,
return LZMA_PROG_ERROR;
// Initialize the Block decoder.
- block_decoder = LZMA_NEXT_CODER_INIT;
- ret = lzma_block_decoder_init(&block_decoder, allocator, block);
+ lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT;
+ lzma_ret ret = lzma_block_decoder_init(
+ &block_decoder, allocator, block);
if (ret == LZMA_OK) {
// Save the positions so that we can restore them in case
diff --git a/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c b/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c
index 136f7f573..39e263aa4 100644
--- a/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c
@@ -10,6 +10,7 @@
//
///////////////////////////////////////////////////////////////////////////////
+#include "block_buffer_encoder.h"
#include "block_encoder.h"
#include "filter_encoder.h"
#include "lzma2_encoder.h"
@@ -28,11 +29,9 @@
+ LZMA_CHECK_SIZE_MAX + 3) & ~3)
-static lzma_vli
-lzma2_bound(lzma_vli uncompressed_size)
+static uint64_t
+lzma2_bound(uint64_t uncompressed_size)
{
- lzma_vli overhead;
-
// Prevent integer overflow in overhead calculation.
if (uncompressed_size > COMPRESSED_SIZE_MAX)
return 0;
@@ -41,7 +40,7 @@ lzma2_bound(lzma_vli uncompressed_size)
// uncompressed_size up to the next multiple of LZMA2_CHUNK_MAX,
// multiply by the size of per-chunk header, and add one byte for
// the end marker.
- overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
+ const uint64_t overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
/ LZMA2_CHUNK_MAX)
* LZMA2_HEADER_UNCOMPRESSED + 1;
@@ -53,30 +52,36 @@ lzma2_bound(lzma_vli uncompressed_size)
}
-extern LZMA_API(size_t)
-lzma_block_buffer_bound(size_t uncompressed_size)
+extern uint64_t
+lzma_block_buffer_bound64(uint64_t uncompressed_size)
{
- // For now, if the data doesn't compress, we always use uncompressed
- // chunks of LZMA2. In future we may use Subblock filter too, but
- // but for simplicity we probably will still use the same bound
- // calculation even though Subblock filter would have slightly less
- // overhead.
- lzma_vli lzma2_size = lzma2_bound(uncompressed_size);
+ // If the data doesn't compress, we always use uncompressed
+ // LZMA2 chunks.
+ uint64_t lzma2_size = lzma2_bound(uncompressed_size);
if (lzma2_size == 0)
return 0;
// Take Block Padding into account.
- lzma2_size = (lzma2_size + 3) & ~LZMA_VLI_C(3);
+ lzma2_size = (lzma2_size + 3) & ~UINT64_C(3);
-#if SIZE_MAX < LZMA_VLI_MAX
- // Catch the possible integer overflow on 32-bit systems. There's no
- // overflow on 64-bit systems, because lzma2_bound() already takes
+ // No risk of integer overflow because lzma2_bound() already takes
// into account the size of the headers in the Block.
- if (SIZE_MAX - HEADERS_BOUND < lzma2_size)
+ return HEADERS_BOUND + lzma2_size;
+}
+
+
+extern LZMA_API(size_t)
+lzma_block_buffer_bound(size_t uncompressed_size)
+{
+ uint64_t ret = lzma_block_buffer_bound64(uncompressed_size);
+
+#if SIZE_MAX < UINT64_MAX
+ // Catch the possible integer overflow on 32-bit systems.
+ if (ret > SIZE_MAX)
return 0;
#endif
- return HEADERS_BOUND + lzma2_size;
+ return ret;
}
@@ -84,17 +89,12 @@ static lzma_ret
block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- size_t in_pos = 0;
- uint8_t control = 0x01; // Dictionary reset
- lzma_filter *filters_orig;
-
- // TODO: Figure out if the last filter is LZMA2 or Subblock and use
- // that filter to encode the uncompressed chunks.
-
// Use LZMA2 uncompressed chunks. We wouldn't need a dictionary at
// all, but LZMA2 always requires a dictionary, so use the minimum
// value to minimize memory usage of the decoder.
- lzma_options_lzma lzma2 = { LZMA_DICT_SIZE_MIN };
+ lzma_options_lzma lzma2 = {
+ .dict_size = LZMA_DICT_SIZE_MIN,
+ };
lzma_filter filters[2];
filters[0].id = LZMA_FILTER_LZMA2;
@@ -103,7 +103,7 @@ block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
// Set the above filter options to *block temporarily so that we can
// encode the Block Header.
- filters_orig = block->filters;
+ lzma_filter *filters_orig = block->filters;
block->filters = filters;
if (lzma_block_header_size(block) != LZMA_OK) {
@@ -132,17 +132,18 @@ block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
*out_pos += block->header_size;
// Encode the data using LZMA2 uncompressed chunks.
+ size_t in_pos = 0;
+ uint8_t control = 0x01; // Dictionary reset
while (in_pos < in_size) {
- size_t copy_size;
-
// Control byte: Indicate uncompressed chunk, of which
// the first resets the dictionary.
out[(*out_pos)++] = control;
control = 0x02; // No dictionary reset
// Size of the uncompressed chunk
- copy_size = my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
+ const size_t copy_size
+ = my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
out[(*out_pos)++] = (copy_size - 1) >> 8;
out[(*out_pos)++] = (copy_size - 1) & 0xFF;
@@ -163,27 +164,18 @@ block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
static lzma_ret
-block_encode_normal(lzma_block *block, lzma_allocator *allocator,
+block_encode_normal(lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- size_t out_start;
- lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
- lzma_ret ret;
-
// Find out the size of the Block Header.
- block->compressed_size = lzma2_bound(in_size);
- if (block->compressed_size == 0)
- return LZMA_DATA_ERROR;
-
- block->uncompressed_size = in_size;
return_if_error(lzma_block_header_size(block));
// Reserve space for the Block Header and skip it for now.
if (out_size - *out_pos <= block->header_size)
return LZMA_BUF_ERROR;
- out_start = *out_pos;
+ const size_t out_start = *out_pos;
*out_pos += block->header_size;
// Limit out_size so that we stop encoding if the output would grow
@@ -193,7 +185,8 @@ block_encode_normal(lzma_block *block, lzma_allocator *allocator,
// TODO: In many common cases this could be optimized to use
// significantly less memory.
- ret = lzma_raw_encoder_init(
+ lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
+ lzma_ret ret = lzma_raw_encoder_init(
&raw_encoder, allocator, block->filters);
if (ret == LZMA_OK) {
@@ -227,15 +220,12 @@ block_encode_normal(lzma_block *block, lzma_allocator *allocator,
}
-extern LZMA_API(lzma_ret)
-lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
+static lzma_ret
+block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size,
- uint8_t *out, size_t *out_pos, size_t out_size)
+ uint8_t *out, size_t *out_pos, size_t out_size,
+ bool try_to_compress)
{
- size_t check_size;
- lzma_ret ret;
- size_t i;
-
// Validate the arguments.
if (block == NULL || (in == NULL && in_size != 0) || out == NULL
|| out_pos == NULL || *out_pos > out_size)
@@ -243,11 +233,11 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
// The contents of the structure may depend on the version so
// check the version before validating the contents of *block.
- if (block->version != 0)
+ if (block->version > 1)
return LZMA_OPTIONS_ERROR;
if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX
- || block->filters == NULL)
+ || (try_to_compress && block->filters == NULL))
return LZMA_PROG_ERROR;
if (!lzma_check_is_supported(block->check))
@@ -259,7 +249,7 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
out_size -= (out_size - *out_pos) & 3;
// Get the size of the Check field.
- check_size = lzma_check_size(block->check);
+ const size_t check_size = lzma_check_size(block->check);
assert(check_size != UINT32_MAX);
// Reserve space for the Check field.
@@ -268,9 +258,19 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
out_size -= check_size;
+ // Initialize block->uncompressed_size and calculate the worst-case
+ // value for block->compressed_size.
+ block->uncompressed_size = in_size;
+ block->compressed_size = lzma2_bound(in_size);
+ if (block->compressed_size == 0)
+ return LZMA_DATA_ERROR;
+
// Do the actual compression.
- ret = block_encode_normal(block, allocator,
- in, in_size, out, out_pos, out_size);
+ lzma_ret ret = LZMA_BUF_ERROR;
+ if (try_to_compress)
+ ret = block_encode_normal(block, allocator,
+ in, in_size, out, out_pos, out_size);
+
if (ret != LZMA_OK) {
// If the error was something else than output buffer
// becoming full, return the error now.
@@ -291,7 +291,7 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
// Block Padding. No buffer overflow here, because we already adjusted
// out_size so that (out_size - out_start) is a multiple of four.
// Thus, if the buffer is full, the loop body can never run.
- for (i = (size_t)(block->compressed_size); i & 3; ++i) {
+ for (size_t i = (size_t)(block->compressed_size); i & 3; ++i) {
assert(*out_pos < out_size);
out[(*out_pos)++] = 0x00;
}
@@ -313,3 +313,25 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
return LZMA_OK;
}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
+{
+ return block_buffer_encode(block, allocator,
+ in, in_size, out, out_pos, out_size, true);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_uncomp_encode(lzma_block *block,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
+{
+ // It won't allocate any memory from heap so no need
+ // for lzma_allocator.
+ return block_buffer_encode(block, NULL,
+ in, in_size, out, out_pos, out_size, false);
+}
diff --git a/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.h b/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.h
new file mode 100644
index 000000000..653207f73
--- /dev/null
+++ b/Utilities/cmliblzma/liblzma/common/block_buffer_encoder.h
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file block_buffer_encoder.h
+/// \brief Single-call .xz Block encoder
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_BUFFER_ENCODER_H
+#define LZMA_BLOCK_BUFFER_ENCODER_H
+
+#include "common.h"
+
+
+/// uint64_t version of lzma_block_buffer_bound(). It is used by
+/// stream_encoder_mt.c. Probably the original lzma_block_buffer_bound()
+/// should have been 64-bit, but fixing it would break the ABI.
+extern uint64_t lzma_block_buffer_bound64(uint64_t uncompressed_size);
+
+#endif
diff --git a/Utilities/cmliblzma/liblzma/common/block_decoder.c b/Utilities/cmliblzma/liblzma/common/block_decoder.c
index 35996e7cf..075bd279f 100644
--- a/Utilities/cmliblzma/liblzma/common/block_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_decoder.c
@@ -15,7 +15,7 @@
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_CODE,
SEQ_PADDING,
@@ -45,7 +45,10 @@ struct lzma_coder_s {
/// Check of the uncompressed data
lzma_check_state check;
-};
+
+ /// True if the integrity check won't be calculated and verified.
+ bool ignore_check;
+} lzma_block_coder;
static inline bool
@@ -71,11 +74,13 @@ is_size_valid(lzma_vli size, lzma_vli reference)
static lzma_ret
-block_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+block_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_block_coder *coder = coder_ptr;
+
switch (coder->sequence) {
case SEQ_CODE: {
const size_t in_start = *in_pos;
@@ -97,8 +102,9 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->block->uncompressed_size))
return LZMA_DATA_ERROR;
- lzma_check_update(&coder->check, coder->block->check,
- out + out_start, out_used);
+ if (!coder->ignore_check)
+ lzma_check_update(&coder->check, coder->block->check,
+ out + out_start, out_used);
if (ret != LZMA_STREAM_END)
return ret;
@@ -140,7 +146,9 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
if (coder->block->check == LZMA_CHECK_NONE)
return LZMA_STREAM_END;
- lzma_check_finish(&coder->check, coder->block->check);
+ if (!coder->ignore_check)
+ lzma_check_finish(&coder->check, coder->block->check);
+
coder->sequence = SEQ_CHECK;
// Fall through
@@ -155,7 +163,8 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
// Validate the Check only if we support it.
// coder->check.buffer may be uninitialized
// when the Check ID is not supported.
- if (lzma_check_is_supported(coder->block->check)
+ if (!coder->ignore_check
+ && lzma_check_is_supported(coder->block->check)
&& memcmp(coder->block->raw_check,
coder->check.buffer.u8,
check_size) != 0)
@@ -170,8 +179,9 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
-block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+block_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_block_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
@@ -179,7 +189,7 @@ block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
extern lzma_ret
-lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
lzma_block *block)
{
lzma_next_coder_init(&lzma_block_decoder_init, next, allocator);
@@ -191,27 +201,29 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|| !lzma_vli_is_valid(block->uncompressed_size))
return LZMA_PROG_ERROR;
- // Allocate and initialize *next->coder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ // Allocate *next->coder if needed.
+ lzma_block_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &block_decode;
next->end = &block_decoder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Basic initializations
- next->coder->sequence = SEQ_CODE;
- next->coder->block = block;
- next->coder->compressed_size = 0;
- next->coder->uncompressed_size = 0;
+ coder->sequence = SEQ_CODE;
+ coder->block = block;
+ coder->compressed_size = 0;
+ coder->uncompressed_size = 0;
// If Compressed Size is not known, we calculate the maximum allowed
// value so that encoded size of the Block (including Block Padding)
// is still a valid VLI and a multiple of four.
- next->coder->compressed_limit
+ coder->compressed_limit
= block->compressed_size == LZMA_VLI_UNKNOWN
? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
- block->header_size
@@ -221,11 +233,14 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Initialize the check. It's caller's problem if the Check ID is not
// supported, and the Block decoder cannot verify the Check field.
// Caller can test lzma_check_is_supported(block->check).
- next->coder->check_pos = 0;
- lzma_check_init(&next->coder->check, block->check);
+ coder->check_pos = 0;
+ lzma_check_init(&coder->check, block->check);
+
+ coder->ignore_check = block->version >= 1
+ ? block->ignore_check : false;
// Initialize the filter chain.
- return lzma_raw_decoder_init(&next->coder->next, allocator,
+ return lzma_raw_decoder_init(&coder->next, allocator,
block->filters);
}
@@ -233,7 +248,7 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_block_decoder(lzma_stream *strm, lzma_block *block)
{
- lzma_next_strm_init1(lzma_block_decoder_init, strm, block);
+ lzma_next_strm_init(lzma_block_decoder_init, strm, block);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/Utilities/cmliblzma/liblzma/common/block_decoder.h b/Utilities/cmliblzma/liblzma/common/block_decoder.h
index 7da9df63f..718c5ced8 100644
--- a/Utilities/cmliblzma/liblzma/common/block_decoder.h
+++ b/Utilities/cmliblzma/liblzma/common/block_decoder.h
@@ -17,6 +17,6 @@
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_block *block);
+ const lzma_allocator *allocator, lzma_block *block);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/block_encoder.c b/Utilities/cmliblzma/liblzma/common/block_encoder.c
index ed748273e..168846ad6 100644
--- a/Utilities/cmliblzma/liblzma/common/block_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_encoder.c
@@ -15,7 +15,7 @@
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
/// The filters in the chain; initialized with lzma_raw_decoder_init().
lzma_next_coder next;
@@ -41,15 +41,17 @@ struct lzma_coder_s {
/// Check of the uncompressed data
lzma_check_state check;
-};
+} lzma_block_coder;
static lzma_ret
-block_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+block_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_block_coder *coder = coder_ptr;
+
// Check that our amount of input stays in proper limits.
if (LZMA_VLI_MAX - coder->uncompressed_size < in_size - *in_pos)
return LZMA_DATA_ERROR;
@@ -134,8 +136,9 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
static void
-block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+block_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_block_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
@@ -143,10 +146,12 @@ block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-block_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+block_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_block_coder *coder = coder_ptr;
+
if (coder->sequence != SEQ_CODE)
return LZMA_PROG_ERROR;
@@ -156,7 +161,7 @@ block_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
extern lzma_ret
-lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
lzma_block *block)
{
lzma_next_coder_init(&lzma_block_encoder_init, next, allocator);
@@ -166,7 +171,7 @@ lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// The contents of the structure may depend on the version so
// check the version first.
- if (block->version != 0)
+ if (block->version > 1)
return LZMA_OPTIONS_ERROR;
// If the Check ID is not supported, we cannot calculate the check and
@@ -178,37 +183,38 @@ lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
return LZMA_UNSUPPORTED_CHECK;
// Allocate and initialize *next->coder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_block_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &block_encode;
next->end = &block_encoder_end;
next->update = &block_encoder_update;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Basic initializations
- next->coder->sequence = SEQ_CODE;
- next->coder->block = block;
- next->coder->compressed_size = 0;
- next->coder->uncompressed_size = 0;
- next->coder->pos = 0;
+ coder->sequence = SEQ_CODE;
+ coder->block = block;
+ coder->compressed_size = 0;
+ coder->uncompressed_size = 0;
+ coder->pos = 0;
// Initialize the check
- lzma_check_init(&next->coder->check, block->check);
+ lzma_check_init(&coder->check, block->check);
// Initialize the requested filters.
- return lzma_raw_encoder_init(&next->coder->next, allocator,
- block->filters);
+ return lzma_raw_encoder_init(&coder->next, allocator, block->filters);
}
extern LZMA_API(lzma_ret)
lzma_block_encoder(lzma_stream *strm, lzma_block *block)
{
- lzma_next_strm_init1(lzma_block_encoder_init, strm, block);
+ lzma_next_strm_init(lzma_block_encoder_init, strm, block);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/Utilities/cmliblzma/liblzma/common/block_encoder.h b/Utilities/cmliblzma/liblzma/common/block_encoder.h
index b9eff0be2..bd97c186e 100644
--- a/Utilities/cmliblzma/liblzma/common/block_encoder.h
+++ b/Utilities/cmliblzma/liblzma/common/block_encoder.h
@@ -42,6 +42,6 @@
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_block *block);
+ const lzma_allocator *allocator, lzma_block *block);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/block_header_decoder.c b/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
index f6e470e69..1dd982f6b 100644
--- a/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
@@ -15,14 +15,12 @@
static void
-free_properties(lzma_block *block, lzma_allocator *allocator)
+free_properties(lzma_block *block, const lzma_allocator *allocator)
{
- size_t i;
-
// Free allocated filter options. The last array member is not
// touched after the initialization in the beginning of
// lzma_block_header_decode(), so we don't need to touch that here.
- for (i = 0; i < LZMA_FILTERS_MAX; ++i) {
+ for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
lzma_free(block->filters[i].options, allocator);
block->filters[i].id = LZMA_VLI_UNKNOWN;
block->filters[i].options = NULL;
@@ -34,15 +32,8 @@ free_properties(lzma_block *block, lzma_allocator *allocator)
extern LZMA_API(lzma_ret)
lzma_block_header_decode(lzma_block *block,
- lzma_allocator *allocator, const uint8_t *in)
+ const lzma_allocator *allocator, const uint8_t *in)
{
- const size_t filter_count = (in[1] & 3) + 1;
- size_t in_size;
- size_t i;
-
- // Start after the Block Header Size and Block Flags fields.
- size_t in_pos = 2;
-
// NOTE: We consider the header to be corrupt not only when the
// CRC32 doesn't match, but also when variable-length integers
// are invalid or over 63 bits, or if the header is too small
@@ -50,13 +41,21 @@ lzma_block_header_decode(lzma_block *block,
// Initialize the filter options array. This way the caller can
// safely free() the options even if an error occurs in this function.
- for (i = 0; i <= LZMA_FILTERS_MAX; ++i) {
+ for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
block->filters[i].id = LZMA_VLI_UNKNOWN;
block->filters[i].options = NULL;
}
- // Always zero for now.
- block->version = 0;
+ // Versions 0 and 1 are supported. If a newer version was specified,
+ // we need to downgrade it.
+ if (block->version > 1)
+ block->version = 1;
+
+ // This isn't a Block Header option, but since the decompressor will
+ // read it if version >= 1, it's better to initialize it here than
+ // to expect the caller to do it since in almost all cases this
+ // should be false.
+ block->ignore_check = false;
// Validate Block Header Size and Check type. The caller must have
// already set these, so it is a programming error if this test fails.
@@ -65,7 +64,7 @@ lzma_block_header_decode(lzma_block *block,
return LZMA_PROG_ERROR;
// Exclude the CRC32 field.
- in_size = block->header_size - 4;
+ const size_t in_size = block->header_size - 4;
// Verify CRC32
if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size))
@@ -75,6 +74,9 @@ lzma_block_header_decode(lzma_block *block,
if (in[1] & 0x3C)
return LZMA_OPTIONS_ERROR;
+ // Start after the Block Header Size and Block Flags fields.
+ size_t in_pos = 2;
+
// Compressed Size
if (in[1] & 0x40) {
return_if_error(lzma_vli_decode(&block->compressed_size,
@@ -96,7 +98,8 @@ lzma_block_header_decode(lzma_block *block,
block->uncompressed_size = LZMA_VLI_UNKNOWN;
// Filter Flags
- for (i = 0; i < filter_count; ++i) {
+ const size_t filter_count = (in[1] & 3) + 1;
+ for (size_t i = 0; i < filter_count; ++i) {
const lzma_ret ret = lzma_filter_flags_decode(
&block->filters[i], allocator,
in, &in_pos, in_size);
diff --git a/Utilities/cmliblzma/liblzma/common/block_header_encoder.c b/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
index 650295c00..5c5f5424a 100644
--- a/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
@@ -17,14 +17,12 @@
extern LZMA_API(lzma_ret)
lzma_block_header_size(lzma_block *block)
{
- size_t i;
+ if (block->version > 1)
+ return LZMA_OPTIONS_ERROR;
// Block Header Size + Block Flags + CRC32.
uint32_t size = 1 + 1 + 4;
- if (block->version != 0)
- return LZMA_OPTIONS_ERROR;
-
// Compressed Size
if (block->compressed_size != LZMA_VLI_UNKNOWN) {
const uint32_t add = lzma_vli_size(block->compressed_size);
@@ -47,13 +45,12 @@ lzma_block_header_size(lzma_block *block)
if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
return LZMA_PROG_ERROR;
- for (i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
- uint32_t add;
-
+ for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
// Don't allow too many filters.
if (i == LZMA_FILTERS_MAX)
return LZMA_PROG_ERROR;
+ uint32_t add;
return_if_error(lzma_filter_flags_size(&add,
block->filters + i));
@@ -76,23 +73,20 @@ lzma_block_header_size(lzma_block *block)
extern LZMA_API(lzma_ret)
lzma_block_header_encode(const lzma_block *block, uint8_t *out)
{
- size_t out_size;
- size_t out_pos = 2;
- size_t filter_count = 0;
-
// Validate everything but filters.
if (lzma_block_unpadded_size(block) == 0
|| !lzma_vli_is_valid(block->uncompressed_size))
return LZMA_PROG_ERROR;
// Indicate the size of the buffer _excluding_ the CRC32 field.
- out_size = block->header_size - 4;
+ const size_t out_size = block->header_size - 4;
// Store the Block Header Size.
out[0] = out_size / 4;
// We write Block Flags in pieces.
out[1] = 0x00;
+ size_t out_pos = 2;
// Compressed Size
if (block->compressed_size != LZMA_VLI_UNKNOWN) {
@@ -114,6 +108,7 @@ lzma_block_header_encode(const lzma_block *block, uint8_t *out)
if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
return LZMA_PROG_ERROR;
+ size_t filter_count = 0;
do {
// There can be a maximum of four filters.
if (filter_count == LZMA_FILTERS_MAX)
diff --git a/Utilities/cmliblzma/liblzma/common/block_util.c b/Utilities/cmliblzma/liblzma/common/block_util.c
index 4cd34d100..00c7fe8d5 100644
--- a/Utilities/cmliblzma/liblzma/common/block_util.c
+++ b/Utilities/cmliblzma/liblzma/common/block_util.c
@@ -17,14 +17,11 @@
extern LZMA_API(lzma_ret)
lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
{
- uint32_t container_size;
- lzma_vli compressed_size;
-
// Validate everything but Uncompressed Size and filters.
if (lzma_block_unpadded_size(block) == 0)
return LZMA_PROG_ERROR;
- container_size = block->header_size
+ const uint32_t container_size = block->header_size
+ lzma_check_size(block->check);
// Validate that Compressed Size will be greater than zero.
@@ -34,7 +31,7 @@ lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
// Calculate what Compressed Size is supposed to be.
// If Compressed Size was present in Block Header,
// compare that the new value matches it.
- compressed_size = unpadded_size - container_size;
+ const lzma_vli compressed_size = unpadded_size - container_size;
if (block->compressed_size != LZMA_VLI_UNKNOWN
&& block->compressed_size != compressed_size)
return LZMA_DATA_ERROR;
@@ -48,15 +45,13 @@ lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
extern LZMA_API(lzma_vli)
lzma_block_unpadded_size(const lzma_block *block)
{
- lzma_vli unpadded_size;
-
// Validate the values that we are interested in i.e. all but
// Uncompressed Size and the filters.
//
// NOTE: This function is used for validation too, so it is
// essential that these checks are always done even if
// Compressed Size is unknown.
- if (block == NULL || block->version != 0
+ if (block == NULL || block->version > 1
|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
|| (block->header_size & 3)
@@ -71,7 +66,7 @@ lzma_block_unpadded_size(const lzma_block *block)
return LZMA_VLI_UNKNOWN;
// Calculate Unpadded Size and validate it.
- unpadded_size = block->compressed_size
+ const lzma_vli unpadded_size = block->compressed_size
+ block->header_size
+ lzma_check_size(block->check);
diff --git a/Utilities/cmliblzma/liblzma/common/common.c b/Utilities/cmliblzma/liblzma/common/common.c
index 2e723c8fe..57e3f8ebd 100644
--- a/Utilities/cmliblzma/liblzma/common/common.c
+++ b/Utilities/cmliblzma/liblzma/common/common.c
@@ -36,14 +36,14 @@ lzma_version_string(void)
///////////////////////
extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
-lzma_alloc(size_t size, lzma_allocator *allocator)
+lzma_alloc(size_t size, const lzma_allocator *allocator)
{
- void *ptr;
-
// Some malloc() variants return NULL if called with size == 0.
if (size == 0)
size = 1;
+ void *ptr;
+
if (allocator != NULL && allocator->alloc != NULL)
ptr = allocator->alloc(allocator->opaque, 1, size);
else
@@ -53,8 +53,29 @@ lzma_alloc(size_t size, lzma_allocator *allocator)
}
+extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
+lzma_alloc_zero(size_t size, const lzma_allocator *allocator)
+{
+ // Some calloc() variants return NULL if called with size == 0.
+ if (size == 0)
+ size = 1;
+
+ void *ptr;
+
+ if (allocator != NULL && allocator->alloc != NULL) {
+ ptr = allocator->alloc(allocator->opaque, 1, size);
+ if (ptr != NULL)
+ memzero(ptr, size);
+ } else {
+ ptr = calloc(1, size);
+ }
+
+ return ptr;
+}
+
+
extern void
-lzma_free(void *ptr, lzma_allocator *allocator)
+lzma_free(void *ptr, const lzma_allocator *allocator)
{
if (allocator != NULL && allocator->free != NULL)
allocator->free(allocator->opaque, ptr);
@@ -70,9 +91,9 @@ lzma_free(void *ptr, lzma_allocator *allocator)
//////////
extern size_t
-lzma_bufcpy(const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size)
+lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size)
{
const size_t in_avail = in_size - *in_pos;
const size_t out_avail = out_size - *out_pos;
@@ -88,7 +109,7 @@ lzma_bufcpy(const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
extern lzma_ret
-lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
lzma_next_coder_init(filters[0].init, next, allocator);
@@ -99,7 +120,7 @@ lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
-lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *reversed_filters)
{
// Check that the application isn't trying to change the Filter ID.
@@ -117,7 +138,7 @@ lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
extern void
-lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
+lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
{
if (next->init != (uintptr_t)(NULL)) {
// To avoid tiny end functions that simply call
@@ -156,10 +177,8 @@ lzma_strm_init(lzma_stream *strm)
strm->internal->next = LZMA_NEXT_CODER_INIT;
}
- strm->internal->supported_actions[LZMA_RUN] = false;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false;
- strm->internal->supported_actions[LZMA_FULL_FLUSH] = false;
- strm->internal->supported_actions[LZMA_FINISH] = false;
+ memzero(strm->internal->supported_actions,
+ sizeof(strm->internal->supported_actions));
strm->internal->sequence = ISEQ_RUN;
strm->internal->allow_buf_error = false;
@@ -173,16 +192,12 @@ lzma_strm_init(lzma_stream *strm)
extern LZMA_API(lzma_ret)
lzma_code(lzma_stream *strm, lzma_action action)
{
- size_t in_pos = 0;
- size_t out_pos = 0;
- lzma_ret ret;
-
// Sanity checks
if ((strm->next_in == NULL && strm->avail_in != 0)
|| (strm->next_out == NULL && strm->avail_out != 0)
|| strm->internal == NULL
|| strm->internal->next.code == NULL
- || (unsigned int)(action) > LZMA_FINISH
+ || (unsigned int)(action) > LZMA_ACTION_MAX
|| !strm->internal->supported_actions[action])
return LZMA_PROG_ERROR;
@@ -217,6 +232,10 @@ lzma_code(lzma_stream *strm, lzma_action action)
case LZMA_FINISH:
strm->internal->sequence = ISEQ_FINISH;
break;
+
+ case LZMA_FULL_BARRIER:
+ strm->internal->sequence = ISEQ_FULL_BARRIER;
+ break;
}
break;
@@ -244,6 +263,13 @@ lzma_code(lzma_stream *strm, lzma_action action)
break;
+ case ISEQ_FULL_BARRIER:
+ if (action != LZMA_FULL_BARRIER
+ || strm->internal->avail_in != strm->avail_in)
+ return LZMA_PROG_ERROR;
+
+ break;
+
case ISEQ_END:
return LZMA_STREAM_END;
@@ -252,7 +278,9 @@ lzma_code(lzma_stream *strm, lzma_action action)
return LZMA_PROG_ERROR;
}
- ret = strm->internal->next.code(
+ size_t in_pos = 0;
+ size_t out_pos = 0;
+ lzma_ret ret = strm->internal->next.code(
strm->internal->next.coder, strm->allocator,
strm->next_in, &in_pos, strm->avail_in,
strm->next_out, &out_pos, strm->avail_out, action);
@@ -267,7 +295,9 @@ lzma_code(lzma_stream *strm, lzma_action action)
strm->internal->avail_in = strm->avail_in;
- switch (ret) {
+ // Cast is needed to silence a warning about LZMA_TIMED_OUT, which
+ // isn't part of lzma_ret enumeration.
+ switch ((unsigned int)(ret)) {
case LZMA_OK:
// Don't return LZMA_BUF_ERROR when it happens the first time.
// This is to avoid returning LZMA_BUF_ERROR when avail_out
@@ -283,9 +313,16 @@ lzma_code(lzma_stream *strm, lzma_action action)
}
break;
+ case LZMA_TIMED_OUT:
+ strm->internal->allow_buf_error = false;
+ ret = LZMA_OK;
+ break;
+
case LZMA_STREAM_END:
if (strm->internal->sequence == ISEQ_SYNC_FLUSH
- || strm->internal->sequence == ISEQ_FULL_FLUSH)
+ || strm->internal->sequence == ISEQ_FULL_FLUSH
+ || strm->internal->sequence
+ == ISEQ_FULL_BARRIER)
strm->internal->sequence = ISEQ_RUN;
else
strm->internal->sequence = ISEQ_END;
@@ -325,6 +362,22 @@ lzma_end(lzma_stream *strm)
}
+extern LZMA_API(void)
+lzma_get_progress(lzma_stream *strm,
+ uint64_t *progress_in, uint64_t *progress_out)
+{
+ if (strm->internal->next.get_progress != NULL) {
+ strm->internal->next.get_progress(strm->internal->next.coder,
+ progress_in, progress_out);
+ } else {
+ *progress_in = strm->total_in;
+ *progress_out = strm->total_out;
+ }
+
+ return;
+}
+
+
extern LZMA_API(lzma_check)
lzma_get_check(const lzma_stream *strm)
{
@@ -382,8 +435,10 @@ lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
|| strm->internal->next.memconfig == NULL)
return LZMA_PROG_ERROR;
- if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
- return LZMA_MEMLIMIT_ERROR;
+ // Zero is a special value that cannot be used as an actual limit.
+ // If 0 was specified, use 1 instead.
+ if (new_memlimit == 0)
+ new_memlimit = 1;
return strm->internal->next.memconfig(strm->internal->next.coder,
&memusage, &old_memlimit, new_memlimit);
diff --git a/Utilities/cmliblzma/liblzma/common/common.h b/Utilities/cmliblzma/liblzma/common/common.h
index a6a28189e..dde3ae0ec 100644
--- a/Utilities/cmliblzma/liblzma/common/common.h
+++ b/Utilities/cmliblzma/liblzma/common/common.h
@@ -48,6 +48,13 @@
#define LZMA_BUFFER_SIZE 4096
+/// Maximum number of worker threads within one multithreaded component.
+/// The limit exists solely to make it simpler to prevent integer overflows
+/// when allocating structures etc. This should be big enough for now...
+/// the code won't scale anywhere close to this number anyway.
+#define LZMA_THREADS_MAX 16384
+
+
/// Starting value for memory usage estimates. Instead of calculating size
/// of _every_ structure and taking into account malloc() overhead etc., we
/// add a base size to all memory usage estimates. It's not very accurate
@@ -65,12 +72,20 @@
( LZMA_TELL_NO_CHECK \
| LZMA_TELL_UNSUPPORTED_CHECK \
| LZMA_TELL_ANY_CHECK \
+ | LZMA_IGNORE_CHECK \
| LZMA_CONCATENATED )
-/// Type of encoder/decoder specific data; the actual structure is defined
-/// differently in different coders.
-typedef struct lzma_coder_s lzma_coder;
+/// Largest valid lzma_action value as unsigned integer.
+#define LZMA_ACTION_MAX ((unsigned int)(LZMA_FULL_BARRIER))
+
+
+/// Special return value (lzma_ret) to indicate that a timeout was reached
+/// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to
+/// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because
+/// there's no need to have it in the public API.
+#define LZMA_TIMED_OUT 32
+
typedef struct lzma_next_coder_s lzma_next_coder;
@@ -79,7 +94,7 @@ typedef struct lzma_filter_info_s lzma_filter_info;
/// Type of a function used to initialize a filter encoder or decoder
typedef lzma_ret (*lzma_init_function)(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters);
/// Type of a function to do some kind of coding work (filters, Stream,
@@ -87,15 +102,15 @@ typedef lzma_ret (*lzma_init_function)(
/// input and output buffers, but for simplicity they still use this same
/// function prototype.
typedef lzma_ret (*lzma_code_function)(
- lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+ void *coder, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action);
/// Type of a function to free the memory allocated for the coder
typedef void (*lzma_end_function)(
- lzma_coder *coder, lzma_allocator *allocator);
+ void *coder, const lzma_allocator *allocator);
/// Raw coder validates and converts an array of lzma_filter structures to
@@ -118,7 +133,7 @@ struct lzma_filter_info_s {
/// Hold data and function pointers of the next filter in the chain.
struct lzma_next_coder_s {
/// Pointer to coder-specific data
- lzma_coder *coder;
+ void *coder;
/// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
/// point to a filter coder.
@@ -138,35 +153,41 @@ struct lzma_next_coder_s {
/// lzma_next_coder.coder.
lzma_end_function end;
+ /// Pointer to a function to get progress information. If this is NULL,
+ /// lzma_stream.total_in and .total_out are used instead.
+ void (*get_progress)(void *coder,
+ uint64_t *progress_in, uint64_t *progress_out);
+
/// Pointer to function to return the type of the integrity check.
/// Most coders won't support this.
- lzma_check (*get_check)(const lzma_coder *coder);
+ lzma_check (*get_check)(const void *coder);
/// Pointer to function to get and/or change the memory usage limit.
/// If new_memlimit == 0, the limit is not changed.
- lzma_ret (*memconfig)(lzma_coder *coder, uint64_t *memusage,
+ lzma_ret (*memconfig)(void *coder, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit);
/// Update the filter-specific options or the whole filter chain
/// in the encoder.
- lzma_ret (*update)(lzma_coder *coder, lzma_allocator *allocator,
+ lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
const lzma_filter *filters,
const lzma_filter *reversed_filters);
};
-/// Constant to initialize lzma_next_coder structure
-static const lzma_next_coder LZMA_NEXT_CODER_INIT =
- {
- NULL,
- LZMA_VLI_UNKNOWN,
- (uintptr_t)(NULL),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- };
+/// Macro to initialize lzma_next_coder structure
+#define LZMA_NEXT_CODER_INIT \
+ (lzma_next_coder){ \
+ .coder = NULL, \
+ .init = (uintptr_t)(NULL), \
+ .id = LZMA_VLI_UNKNOWN, \
+ .code = NULL, \
+ .end = NULL, \
+ .get_progress = NULL, \
+ .get_check = NULL, \
+ .memconfig = NULL, \
+ .update = NULL, \
+ }
/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to
@@ -184,6 +205,7 @@ struct lzma_internal_s {
ISEQ_SYNC_FLUSH,
ISEQ_FULL_FLUSH,
ISEQ_FINISH,
+ ISEQ_FULL_BARRIER,
ISEQ_END,
ISEQ_ERROR,
} sequence;
@@ -194,7 +216,7 @@ struct lzma_internal_s {
size_t avail_in;
/// Indicates which lzma_action values are allowed by next.code.
- bool supported_actions[4];
+ bool supported_actions[LZMA_ACTION_MAX + 1];
/// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
/// made (no input consumed and no output produced by next.code).
@@ -203,15 +225,21 @@ struct lzma_internal_s {
/// Allocates memory
-extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
+extern void *lzma_alloc(size_t size, const lzma_allocator *allocator)
lzma_attribute((__malloc__)) lzma_attr_alloc_size(1);
+/// Allocates memory and zeroes it (like calloc()). This can be faster
+/// than lzma_alloc() + memzero() while being backward compatible with
+/// custom allocators.
+extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
+ lzma_alloc_zero(size_t size, const lzma_allocator *allocator);
+
/// Frees memory
-extern void lzma_free(void *ptr, lzma_allocator *allocator);
+extern void lzma_free(void *ptr, const lzma_allocator *allocator);
/// Allocates strm->internal if it is NULL, and initializes *strm and
-/// strm->internal. This function is only called via lzma_next_strm_init2 macro.
+/// strm->internal. This function is only called via lzma_next_strm_init macro.
extern lzma_ret lzma_strm_init(lzma_stream *strm);
/// Initializes the next filter in the chain, if any. This takes care of
@@ -219,24 +247,26 @@ extern lzma_ret lzma_strm_init(lzma_stream *strm);
/// than the filter being initialized now. This way the actual filter
/// initialization functions don't need to use lzma_next_coder_init macro.
extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
/// Update the next filter in the chain, if any. This checks that
/// the application is not trying to change the Filter IDs.
extern lzma_ret lzma_next_filter_update(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *reversed_filters);
/// Frees the memory allocated for next->coder either using next->end or,
/// if next->end is NULL, using lzma_free.
-extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
+extern void lzma_next_end(lzma_next_coder *next,
+ const lzma_allocator *allocator);
/// Copy as much data as possible from in[] to out[] and update *in_pos
/// and *out_pos accordingly. Returns the number of bytes copied.
-extern size_t lzma_bufcpy(const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size);
+extern size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size);
/// \brief Return if expression doesn't evaluate to LZMA_OK
@@ -269,37 +299,15 @@ do { \
/// (The function being called will use lzma_next_coder_init()). If
/// initialization fails, memory that wasn't freed by func() is freed
/// along strm->internal.
-#define lzma_next_strm_init1(func, strm, arg1) \
+#define lzma_next_strm_init(func, strm, ...) \
do { \
- lzma_ret ret_; \
- return_if_error(lzma_strm_init(strm)); \
- ret_ = func(&(strm)->internal->next, (strm)->allocator, arg1); \
- if (ret_ != LZMA_OK) { \
- lzma_end(strm); \
- return ret_; \
- } \
-} while (0)
-
-#define lzma_next_strm_init2(func, strm, arg1, arg2) \
-do { \
- lzma_ret ret_; \
- return_if_error(lzma_strm_init(strm)); \
- ret_ = func(&(strm)->internal->next, (strm)->allocator, arg1, arg2); \
- if (ret_ != LZMA_OK) { \
- lzma_end(strm); \
- return ret_; \
- } \
-} while (0)
-
-#define lzma_next_strm_init3(func, strm, arg1, arg2, arg3) \
-do { \
- lzma_ret ret_; \
- return_if_error(lzma_strm_init(strm)); \
- ret_ = func(&(strm)->internal->next, (strm)->allocator, arg1, arg2, arg3); \
- if (ret_ != LZMA_OK) { \
- lzma_end(strm); \
- return ret_; \
- } \
+ return_if_error(lzma_strm_init(strm)); \
+ const lzma_ret ret_ = func(&(strm)->internal->next, \
+ (strm)->allocator, __VA_ARGS__); \
+ if (ret_ != LZMA_OK) { \
+ lzma_end(strm); \
+ return ret_; \
+ } \
} while (0)
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c b/Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c
index c4be34ccf..48eb56f5c 100644
--- a/Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c
@@ -15,8 +15,8 @@
extern LZMA_API(lzma_ret)
lzma_easy_buffer_encode(uint32_t preset, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
- uint8_t *out, size_t *out_pos, size_t out_size)
+ const lzma_allocator *allocator, const uint8_t *in,
+ size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size)
{
lzma_options_easy opt_easy;
if (lzma_easy_preset(&opt_easy, preset))
diff --git a/Utilities/cmliblzma/liblzma/common/easy_encoder.c b/Utilities/cmliblzma/liblzma/common/easy_encoder.c
index d13ccd735..5cb492dd0 100644
--- a/Utilities/cmliblzma/liblzma/common/easy_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/easy_encoder.c
@@ -11,7 +11,6 @@
///////////////////////////////////////////////////////////////////////////////
#include "easy_preset.h"
-#include "stream_encoder.h"
extern LZMA_API(lzma_ret)
diff --git a/Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c b/Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c
index 65665c17d..6620986ee 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c
@@ -14,30 +14,27 @@
extern LZMA_API(lzma_ret)
-lzma_raw_buffer_decode(const lzma_filter *filters, lzma_allocator *allocator,
+lzma_raw_buffer_decode(
+ const lzma_filter *filters, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder next = LZMA_NEXT_CODER_INIT;
- size_t in_start;
- size_t out_start;
- lzma_ret ret;
-
// Validate what isn't validated later in filter_common.c.
if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL
|| out_pos == NULL || *out_pos > out_size)
return LZMA_PROG_ERROR;
// Initialize the decoer.
+ lzma_next_coder next = LZMA_NEXT_CODER_INIT;
return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
// Store the positions so that we can restore them if something
// goes wrong.
- in_start = *in_pos;
- out_start = *out_pos;
+ const size_t in_start = *in_pos;
+ const size_t out_start = *out_pos;
// Do the actual decoding and free decoder's memory.
- ret = next.code(next.coder, allocator, in, in_pos, in_size,
+ lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size,
out, out_pos, out_size, LZMA_FINISH);
if (ret == LZMA_STREAM_END) {
diff --git a/Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c b/Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c
index b23329f3e..dda18e3d8 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c
@@ -14,29 +14,27 @@
extern LZMA_API(lzma_ret)
-lzma_raw_buffer_encode(const lzma_filter *filters, lzma_allocator *allocator,
- const uint8_t *in, size_t in_size, uint8_t *out,
- size_t *out_pos, size_t out_size)
+lzma_raw_buffer_encode(
+ const lzma_filter *filters, const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder next = LZMA_NEXT_CODER_INIT;
- size_t out_start;
- size_t in_pos = 0;
- lzma_ret ret;
-
// Validate what isn't validated later in filter_common.c.
if ((in == NULL && in_size != 0) || out == NULL
|| out_pos == NULL || *out_pos > out_size)
return LZMA_PROG_ERROR;
// Initialize the encoder
+ lzma_next_coder next = LZMA_NEXT_CODER_INIT;
return_if_error(lzma_raw_encoder_init(&next, allocator, filters));
// Store the output position so that we can restore it if
// something goes wrong.
- out_start = *out_pos;
+ const size_t out_start = *out_pos;
// Do the actual encoding and free coder's memory.
- ret = next.code(next.coder, allocator, in, &in_pos, in_size,
+ size_t in_pos = 0;
+ lzma_ret ret = next.code(next.coder, allocator, in, &in_pos, in_size,
out, out_pos, out_size, LZMA_FINISH);
lzma_next_end(&next, allocator);
diff --git a/Utilities/cmliblzma/liblzma/common/filter_common.c b/Utilities/cmliblzma/liblzma/common/filter_common.c
index d2b9e086e..9ad5d5d8e 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_common.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_common.c
@@ -36,101 +36,100 @@ static const struct {
} features[] = {
#if defined (HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1)
{
- LZMA_FILTER_LZMA1,
- sizeof(lzma_options_lzma),
- false,
- true,
- true,
+ .id = LZMA_FILTER_LZMA1,
+ .options_size = sizeof(lzma_options_lzma),
+ .non_last_ok = false,
+ .last_ok = true,
+ .changes_size = true,
},
#endif
#if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
{
- LZMA_FILTER_LZMA2,
- sizeof(lzma_options_lzma),
- false,
- true,
- true,
+ .id = LZMA_FILTER_LZMA2,
+ .options_size = sizeof(lzma_options_lzma),
+ .non_last_ok = false,
+ .last_ok = true,
+ .changes_size = true,
},
#endif
#if defined(HAVE_ENCODER_X86) || defined(HAVE_DECODER_X86)
{
- LZMA_FILTER_X86,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_X86,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
{
- LZMA_FILTER_POWERPC,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_POWERPC,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_IA64) || defined(HAVE_DECODER_IA64)
{
- LZMA_FILTER_IA64,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_IA64,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
{
- LZMA_FILTER_ARM,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_ARM,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
{
- LZMA_FILTER_ARMTHUMB,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_ARMTHUMB,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
{
- LZMA_FILTER_SPARC,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_SPARC,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
{
- LZMA_FILTER_DELTA,
- sizeof(lzma_options_delta),
- true,
- false,
- false,
+ .id = LZMA_FILTER_DELTA,
+ .options_size = sizeof(lzma_options_delta),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
{
- LZMA_VLI_UNKNOWN
+ .id = LZMA_VLI_UNKNOWN
}
};
extern LZMA_API(lzma_ret)
lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
- lzma_allocator *allocator)
+ const lzma_allocator *allocator)
{
- size_t i;
- lzma_ret ret;
-
if (src == NULL || dest == NULL)
return LZMA_PROG_ERROR;
+ lzma_ret ret;
+ size_t i;
for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
// There must be a maximum of four filters plus
// the array terminator.
@@ -194,6 +193,10 @@ error:
static lzma_ret
validate_chain(const lzma_filter *filters, size_t *count)
{
+ // There must be at least one filter.
+ if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
+ return LZMA_PROG_ERROR;
+
// Number of non-last filters that may change the size of the data
// significantly (that is, more than 1-2 % or so).
size_t changes_size_count = 0;
@@ -207,11 +210,6 @@ validate_chain(const lzma_filter *filters, size_t *count)
bool last_ok = false;
size_t i = 0;
-
- // There must be at least one filter.
- if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
- return LZMA_PROG_ERROR;
-
do {
size_t j;
for (j = 0; filters[i].id != features[j].id; ++j)
@@ -241,21 +239,18 @@ validate_chain(const lzma_filter *filters, size_t *count)
extern lzma_ret
-lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_raw_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options,
lzma_filter_find coder_find, bool is_encoder)
{
- lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
- size_t count;
- size_t i;
- lzma_ret ret;
-
// Do some basic validation and get the number of filters.
+ size_t count;
return_if_error(validate_chain(options, &count));
// Set the filter functions and copy the options pointer.
+ lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
if (is_encoder) {
- for (i = 0; i < count; ++i) {
+ for (size_t i = 0; i < count; ++i) {
// The order of the filters is reversed in the
// encoder. It allows more efficient handling
// of the uncompressed data.
@@ -271,7 +266,7 @@ lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
filters[j].options = options[i].options;
}
} else {
- for (i = 0; i < count; ++i) {
+ for (size_t i = 0; i < count; ++i) {
const lzma_filter_coder *const fc
= coder_find(options[i].id);
if (fc == NULL || fc->init == NULL)
@@ -288,7 +283,7 @@ lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
filters[count].init = NULL;
// Initialize the filters.
- ret = lzma_next_filter_init(next, allocator, filters);
+ const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
if (ret != LZMA_OK)
lzma_next_end(next, allocator);
@@ -300,9 +295,6 @@ extern uint64_t
lzma_raw_coder_memusage(lzma_filter_find coder_find,
const lzma_filter *filters)
{
- uint64_t total = 0;
- size_t i = 0;
-
// The chain has to have at least one filter.
{
size_t tmp;
@@ -310,6 +302,9 @@ lzma_raw_coder_memusage(lzma_filter_find coder_find,
return UINT64_MAX;
}
+ uint64_t total = 0;
+ size_t i = 0;
+
do {
const lzma_filter_coder *const fc
= coder_find(filters[i].id);
diff --git a/Utilities/cmliblzma/liblzma/common/filter_common.h b/Utilities/cmliblzma/liblzma/common/filter_common.h
index cd61fc072..42a26a24a 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_common.h
+++ b/Utilities/cmliblzma/liblzma/common/filter_common.h
@@ -36,7 +36,7 @@ typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
extern lzma_ret lzma_raw_coder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *filters,
lzma_filter_find coder_find, bool is_encoder);
diff --git a/Utilities/cmliblzma/liblzma/common/filter_decoder.c b/Utilities/cmliblzma/liblzma/common/filter_decoder.c
index cce2b30ea..c75b0a89c 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_decoder.c
@@ -35,7 +35,8 @@ typedef struct {
/// \return - LZMA_OK: Properties decoded successfully.
/// - LZMA_OPTIONS_ERROR: Unsupported properties
/// - LZMA_MEM_ERROR: Memory allocation failed.
- lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
+ lzma_ret (*props_decode)(
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
} lzma_filter_decoder;
@@ -44,74 +45,74 @@ typedef struct {
static const lzma_filter_decoder decoders[] = {
#ifdef HAVE_DECODER_LZMA1
{
- LZMA_FILTER_LZMA1,
- &lzma_lzma_decoder_init,
- &lzma_lzma_decoder_memusage,
- &lzma_lzma_props_decode,
+ .id = LZMA_FILTER_LZMA1,
+ .init = &lzma_lzma_decoder_init,
+ .memusage = &lzma_lzma_decoder_memusage,
+ .props_decode = &lzma_lzma_props_decode,
},
#endif
#ifdef HAVE_DECODER_LZMA2
{
- LZMA_FILTER_LZMA2,
- &lzma_lzma2_decoder_init,
- &lzma_lzma2_decoder_memusage,
- &lzma_lzma2_props_decode,
+ .id = LZMA_FILTER_LZMA2,
+ .init = &lzma_lzma2_decoder_init,
+ .memusage = &lzma_lzma2_decoder_memusage,
+ .props_decode = &lzma_lzma2_props_decode,
},
#endif
#ifdef HAVE_DECODER_X86
{
- LZMA_FILTER_X86,
- &lzma_simple_x86_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_X86,
+ .init = &lzma_simple_x86_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_POWERPC
{
- LZMA_FILTER_POWERPC,
- &lzma_simple_powerpc_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_POWERPC,
+ .init = &lzma_simple_powerpc_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_IA64
{
- LZMA_FILTER_IA64,
- &lzma_simple_ia64_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_IA64,
+ .init = &lzma_simple_ia64_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_ARM
{
- LZMA_FILTER_ARM,
- &lzma_simple_arm_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_ARM,
+ .init = &lzma_simple_arm_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_ARMTHUMB
{
- LZMA_FILTER_ARMTHUMB,
- &lzma_simple_armthumb_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_ARMTHUMB,
+ .init = &lzma_simple_armthumb_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_SPARC
{
- LZMA_FILTER_SPARC,
- &lzma_simple_sparc_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_SPARC,
+ .init = &lzma_simple_sparc_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_DELTA
{
- LZMA_FILTER_DELTA,
- &lzma_delta_decoder_init,
- &lzma_delta_coder_memusage,
- &lzma_delta_props_decode,
+ .id = LZMA_FILTER_DELTA,
+ .init = &lzma_delta_decoder_init,
+ .memusage = &lzma_delta_coder_memusage,
+ .props_decode = &lzma_delta_props_decode,
},
#endif
};
@@ -120,8 +121,7 @@ static const lzma_filter_decoder decoders[] = {
static const lzma_filter_decoder *
decoder_find(lzma_vli id)
{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(decoders); ++i)
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
if (decoders[i].id == id)
return decoders + i;
@@ -137,7 +137,7 @@ lzma_filter_decoder_is_supported(lzma_vli id)
extern lzma_ret
-lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options)
{
return lzma_raw_coder_init(next, allocator,
@@ -148,7 +148,7 @@ lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
{
- lzma_next_strm_init1(lzma_raw_decoder_init, strm, options);
+ lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
@@ -166,14 +166,13 @@ lzma_raw_decoder_memusage(const lzma_filter *filters)
extern LZMA_API(lzma_ret)
-lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
+lzma_properties_decode(lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- const lzma_filter_decoder *const fd = decoder_find(filter->id);
-
// Make it always NULL so that the caller can always safely free() it.
filter->options = NULL;
+ const lzma_filter_decoder *const fd = decoder_find(filter->id);
if (fd == NULL)
return LZMA_OPTIONS_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/common/filter_decoder.h b/Utilities/cmliblzma/liblzma/common/filter_decoder.h
index d5c68bdd4..a2e255fe5 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_decoder.h
+++ b/Utilities/cmliblzma/liblzma/common/filter_decoder.h
@@ -17,7 +17,7 @@
extern lzma_ret lzma_raw_decoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/filter_encoder.c b/Utilities/cmliblzma/liblzma/common/filter_encoder.c
index 9fdb10008..c5d8f3972 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_encoder.c
@@ -30,11 +30,11 @@ typedef struct {
/// invalid, UINT64_MAX is returned.
uint64_t (*memusage)(const void *options);
- /// Calculates the minimum sane size for Blocks (or other types of
- /// chunks) to which the input data can be split to make
- /// multithreaded encoding possible. If this is NULL, it is assumed
- /// that the encoder is fast enough with single thread.
- lzma_vli (*chunk_size)(const void *options);
+ /// Calculates the recommended Uncompressed Size for .xz Blocks to
+ /// which the input data can be split to make multithreaded
+ /// encoding possible. If this is NULL, it is assumed that
+ /// the encoder is fast enough with single thread.
+ uint64_t (*block_size)(const void *options);
/// Tells the size of the Filter Properties field. If options are
/// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed
@@ -56,101 +56,95 @@ typedef struct {
static const lzma_filter_encoder encoders[] = {
#ifdef HAVE_ENCODER_LZMA1
{
- LZMA_FILTER_LZMA1,
- &lzma_lzma_encoder_init,
- &lzma_lzma_encoder_memusage,
- NULL, // FIXME
- NULL,
- 5,
- &lzma_lzma_props_encode,
+ .id = LZMA_FILTER_LZMA1,
+ .init = &lzma_lzma_encoder_init,
+ .memusage = &lzma_lzma_encoder_memusage,
+ .block_size = NULL, // FIXME
+ .props_size_get = NULL,
+ .props_size_fixed = 5,
+ .props_encode = &lzma_lzma_props_encode,
},
#endif
#ifdef HAVE_ENCODER_LZMA2
{
- LZMA_FILTER_LZMA2,
- &lzma_lzma2_encoder_init,
- &lzma_lzma2_encoder_memusage,
- NULL, // FIXME
- NULL,
- 1,
- &lzma_lzma2_props_encode,
+ .id = LZMA_FILTER_LZMA2,
+ .init = &lzma_lzma2_encoder_init,
+ .memusage = &lzma_lzma2_encoder_memusage,
+ .block_size = &lzma_lzma2_block_size, // FIXME
+ .props_size_get = NULL,
+ .props_size_fixed = 1,
+ .props_encode = &lzma_lzma2_props_encode,
},
#endif
#ifdef HAVE_ENCODER_X86
{
- LZMA_FILTER_X86,
- &lzma_simple_x86_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_X86,
+ .init = &lzma_simple_x86_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_POWERPC
{
- LZMA_FILTER_POWERPC,
- &lzma_simple_powerpc_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_POWERPC,
+ .init = &lzma_simple_powerpc_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_IA64
{
- LZMA_FILTER_IA64,
- &lzma_simple_ia64_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_IA64,
+ .init = &lzma_simple_ia64_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_ARM
{
- LZMA_FILTER_ARM,
- &lzma_simple_arm_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_ARM,
+ .init = &lzma_simple_arm_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_ARMTHUMB
{
- LZMA_FILTER_ARMTHUMB,
- &lzma_simple_armthumb_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_ARMTHUMB,
+ .init = &lzma_simple_armthumb_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_SPARC
{
- LZMA_FILTER_SPARC,
- &lzma_simple_sparc_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_SPARC,
+ .init = &lzma_simple_sparc_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_DELTA
{
- LZMA_FILTER_DELTA,
- &lzma_delta_encoder_init,
- &lzma_delta_coder_memusage,
- NULL,
- NULL,
- 1,
- &lzma_delta_props_encode,
+ .id = LZMA_FILTER_DELTA,
+ .init = &lzma_delta_encoder_init,
+ .memusage = &lzma_delta_coder_memusage,
+ .block_size = NULL,
+ .props_size_get = NULL,
+ .props_size_fixed = 1,
+ .props_encode = &lzma_delta_props_encode,
},
#endif
};
@@ -159,8 +153,7 @@ static const lzma_filter_encoder encoders[] = {
static const lzma_filter_encoder *
encoder_find(lzma_vli id)
{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(encoders); ++i)
+ for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i)
if (encoders[i].id == id)
return encoders + i;
@@ -178,10 +171,6 @@ lzma_filter_encoder_is_supported(lzma_vli id)
extern LZMA_API(lzma_ret)
lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
{
- size_t i;
- size_t count = 1;
- lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
-
if (strm->internal->next.update == NULL)
return LZMA_PROG_ERROR;
@@ -191,10 +180,12 @@ lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
// The actual filter chain in the encoder is reversed. Some things
// still want the normal order chain, so we provide both.
+ size_t count = 1;
while (filters[count].id != LZMA_VLI_UNKNOWN)
++count;
- for (i = 0; i < count; ++i)
+ lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
+ for (size_t i = 0; i < count; ++i)
reversed_filters[count - i - 1] = filters[i];
reversed_filters[count].id = LZMA_VLI_UNKNOWN;
@@ -205,7 +196,7 @@ lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
extern lzma_ret
-lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options)
{
return lzma_raw_coder_init(next, allocator,
@@ -216,7 +207,7 @@ lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
{
- lzma_next_strm_init3(lzma_raw_coder_init, strm, options,
+ lzma_next_strm_init(lzma_raw_coder_init, strm, options,
(lzma_filter_find)(&encoder_find), true);
strm->internal->supported_actions[LZMA_RUN] = true;
@@ -235,20 +226,19 @@ lzma_raw_encoder_memusage(const lzma_filter *filters)
}
-/*
-extern LZMA_API(lzma_vli)
-lzma_chunk_size(const lzma_filter *filters)
+extern uint64_t
+lzma_mt_block_size(const lzma_filter *filters)
{
- lzma_vli max = 0;
+ uint64_t max = 0;
for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
const lzma_filter_encoder *const fe
= encoder_find(filters[i].id);
- if (fe->chunk_size != NULL) {
- const lzma_vli size
- = fe->chunk_size(filters[i].options);
- if (size == LZMA_VLI_UNKNOWN)
- return LZMA_VLI_UNKNOWN;
+ if (fe->block_size != NULL) {
+ const uint64_t size
+ = fe->block_size(filters[i].options);
+ if (size == 0)
+ return 0;
if (size > max)
max = size;
@@ -257,7 +247,6 @@ lzma_chunk_size(const lzma_filter *filters)
return max;
}
-*/
extern LZMA_API(lzma_ret)
diff --git a/Utilities/cmliblzma/liblzma/common/filter_encoder.h b/Utilities/cmliblzma/liblzma/common/filter_encoder.h
index 5bc137f64..f1d5683fe 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_encoder.h
+++ b/Utilities/cmliblzma/liblzma/common/filter_encoder.h
@@ -16,12 +16,12 @@
#include "common.h"
-// FIXME: Might become a part of the public API once finished.
-// extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
+// FIXME: Might become a part of the public API.
+extern uint64_t lzma_mt_block_size(const lzma_filter *filters);
extern lzma_ret lzma_raw_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *filters);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c b/Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c
index aa2dbd560..ddfb08594 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c
@@ -15,12 +15,9 @@
extern LZMA_API(lzma_ret)
lzma_filter_flags_decode(
- lzma_filter *filter, lzma_allocator *allocator,
+ lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
{
- lzma_vli props_size;
- lzma_ret ret;
-
// Set the pointer to NULL so the caller can always safely free it.
filter->options = NULL;
@@ -32,6 +29,7 @@ lzma_filter_flags_decode(
return LZMA_DATA_ERROR;
// Size of Properties
+ lzma_vli props_size;
return_if_error(lzma_vli_decode(&props_size, NULL,
in, in_pos, in_size));
@@ -39,7 +37,7 @@ lzma_filter_flags_decode(
if (in_size - *in_pos < props_size)
return LZMA_DATA_ERROR;
- ret = lzma_properties_decode(
+ const lzma_ret ret = lzma_properties_decode(
filter, allocator, in + *in_pos, props_size);
*in_pos += props_size;
diff --git a/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c b/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
index 755c407f6..d110566de 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
@@ -31,8 +31,6 @@ extern LZMA_API(lzma_ret)
lzma_filter_flags_encode(const lzma_filter *filter,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- uint32_t props_size;
-
// Filter ID
if (filter->id >= LZMA_FILTER_RESERVED_START)
return LZMA_PROG_ERROR;
@@ -41,6 +39,7 @@ lzma_filter_flags_encode(const lzma_filter *filter,
out, out_pos, out_size));
// Size of Properties
+ uint32_t props_size;
return_if_error(lzma_properties_size(&props_size, filter));
return_if_error(lzma_vli_encode(props_size, NULL,
out, out_pos, out_size));
diff --git a/Utilities/cmliblzma/liblzma/common/stream_encoder.h b/Utilities/cmliblzma/liblzma/common/hardware_cputhreads.c
index 46a7aed72..f468366a6 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_encoder.h
+++ b/Utilities/cmliblzma/liblzma/common/hardware_cputhreads.c
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file stream_encoder.h
-/// \brief Encodes .xz Streams
+/// \file hardware_cputhreads.c
+/// \brief Get the number of CPU threads or cores
//
// Author: Lasse Collin
//
@@ -10,14 +10,13 @@
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef LZMA_STREAM_ENCODER_H
-#define LZMA_STREAM_ENCODER_H
-
#include "common.h"
+#include "tuklib_cpucores.h"
-extern lzma_ret lzma_stream_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter *filters, lzma_check check);
-#endif
+extern LZMA_API(uint32_t)
+lzma_cputhreads(void)
+{
+ return tuklib_cpucores();
+}
diff --git a/Utilities/cmliblzma/liblzma/common/index.c b/Utilities/cmliblzma/liblzma/common/index.c
index 26135d22c..26e4e519b 100644
--- a/Utilities/cmliblzma/liblzma/common/index.c
+++ b/Utilities/cmliblzma/liblzma/common/index.c
@@ -191,8 +191,8 @@ index_tree_init(index_tree *tree)
/// Helper for index_tree_end()
static void
-index_tree_node_end(index_tree_node *node, lzma_allocator *allocator,
- void (*free_func)(void *node, lzma_allocator *allocator))
+index_tree_node_end(index_tree_node *node, const lzma_allocator *allocator,
+ void (*free_func)(void *node, const lzma_allocator *allocator))
{
// The tree won't ever be very huge, so recursion should be fine.
// 20 levels in the tree is likely quite a lot already in practice.
@@ -202,22 +202,21 @@ index_tree_node_end(index_tree_node *node, lzma_allocator *allocator,
if (node->right != NULL)
index_tree_node_end(node->right, allocator, free_func);
- if (free_func != NULL)
- free_func(node, allocator);
-
- lzma_free(node, allocator);
+ free_func(node, allocator);
return;
}
-/// Free the meory allocated for a tree. If free_func is not NULL,
-/// it is called on each node before freeing the node. This is used
-/// to free the Record groups from each index_stream before freeing
-/// the index_stream itself.
+/// Free the memory allocated for a tree. Each node is freed using the
+/// given free_func which is either &lzma_free or &index_stream_end.
+/// The latter is used to free the Record groups from each index_stream
+/// before freeing the index_stream itself.
static void
-index_tree_end(index_tree *tree, lzma_allocator *allocator,
- void (*free_func)(void *node, lzma_allocator *allocator))
+index_tree_end(index_tree *tree, const lzma_allocator *allocator,
+ void (*free_func)(void *node, const lzma_allocator *allocator))
{
+ assert(free_func != NULL);
+
if (tree->root != NULL)
index_tree_node_end(tree->root, allocator, free_func);
@@ -230,7 +229,6 @@ index_tree_end(index_tree *tree, lzma_allocator *allocator,
static void
index_tree_append(index_tree *tree, index_tree_node *node)
{
- uint32_t up;
node->parent = tree->rightmost;
node->left = NULL;
node->right = NULL;
@@ -259,10 +257,8 @@ index_tree_append(index_tree *tree, index_tree_node *node)
// and thus know the state of the tree just by looking at the node
// count. From the node count we can calculate how many steps to go
// up in the tree to find the rotation root.
- up = tree->count ^ (UINT32_C(1) << bsr32(tree->count));
+ uint32_t up = tree->count ^ (UINT32_C(1) << bsr32(tree->count));
if (up != 0) {
- index_tree_node *pivot;
-
// Locate the root node for the rotation.
up = ctz32(tree->count) + 2;
do {
@@ -270,7 +266,7 @@ index_tree_append(index_tree *tree, index_tree_node *node)
} while (--up > 0);
// Rotate left using node as the rotation root.
- pivot = node->right;
+ index_tree_node *pivot = node->right;
if (node->parent == NULL) {
tree->root = pivot;
@@ -342,8 +338,8 @@ index_tree_locate(const index_tree *tree, lzma_vli target)
/// Allocate and initialize a new Stream using the given base offsets.
static index_stream *
index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base,
- lzma_vli stream_number, lzma_vli block_number_base,
- lzma_allocator *allocator)
+ uint32_t stream_number, lzma_vli block_number_base,
+ const lzma_allocator *allocator)
{
index_stream *s = lzma_alloc(sizeof(index_stream), allocator);
if (s == NULL)
@@ -371,16 +367,17 @@ index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base,
/// Free the memory allocated for a Stream and its Record groups.
static void
-index_stream_end(void *node, lzma_allocator *allocator)
+index_stream_end(void *node, const lzma_allocator *allocator)
{
index_stream *s = node;
- index_tree_end(&s->groups, allocator, NULL);
+ index_tree_end(&s->groups, allocator, &lzma_free);
+ lzma_free(s, allocator);
return;
}
static lzma_index *
-index_init_plain(lzma_allocator *allocator)
+index_init_plain(const lzma_allocator *allocator)
{
lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
if (i != NULL) {
@@ -398,15 +395,13 @@ index_init_plain(lzma_allocator *allocator)
extern LZMA_API(lzma_index *)
-lzma_index_init(lzma_allocator *allocator)
+lzma_index_init(const lzma_allocator *allocator)
{
- index_stream *s;
-
lzma_index *i = index_init_plain(allocator);
if (i == NULL)
return NULL;
- s = index_stream_init(0, 0, 1, 0, allocator);
+ index_stream *s = index_stream_init(0, 0, 1, 0, allocator);
if (s == NULL) {
lzma_free(i, allocator);
return NULL;
@@ -419,7 +414,7 @@ lzma_index_init(lzma_allocator *allocator)
extern LZMA_API(void)
-lzma_index_end(lzma_index *i, lzma_allocator *allocator)
+lzma_index_end(lzma_index *i, const lzma_allocator *allocator)
{
// NOTE: If you modify this function, check also the bottom
// of lzma_index_cat().
@@ -605,8 +600,6 @@ lzma_index_padding_size(const lzma_index *i)
extern LZMA_API(lzma_ret)
lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags)
{
- index_stream *s;
-
if (i == NULL || stream_flags == NULL)
return LZMA_PROG_ERROR;
@@ -614,7 +607,7 @@ lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags)
return_if_error(lzma_stream_flags_compare(
stream_flags, stream_flags));
- s = (index_stream *)(i->streams.rightmost);
+ index_stream *s = (index_stream *)(i->streams.rightmost);
s->stream_flags = *stream_flags;
return LZMA_OK;
@@ -624,17 +617,14 @@ lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags)
extern LZMA_API(lzma_ret)
lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding)
{
- index_stream *s;
- lzma_vli old_stream_padding;
-
if (i == NULL || stream_padding > LZMA_VLI_MAX
|| (stream_padding & 3) != 0)
return LZMA_PROG_ERROR;
- s = (index_stream *)(i->streams.rightmost);
+ index_stream *s = (index_stream *)(i->streams.rightmost);
// Check that the new value won't make the file grow too big.
- old_stream_padding = s->stream_padding;
+ const lzma_vli old_stream_padding = s->stream_padding;
s->stream_padding = 0;
if (lzma_index_file_size(i) + stream_padding > LZMA_VLI_MAX) {
s->stream_padding = old_stream_padding;
@@ -647,29 +637,23 @@ lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding)
extern LZMA_API(lzma_ret)
-lzma_index_append(lzma_index *i, lzma_allocator *allocator,
+lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
lzma_vli unpadded_size, lzma_vli uncompressed_size)
{
- index_stream *s;
- index_group *g;
- lzma_vli compressed_base;
- lzma_vli uncompressed_base;
- uint32_t index_list_size_add;
-
// Validate.
if (i == NULL || unpadded_size < UNPADDED_SIZE_MIN
|| unpadded_size > UNPADDED_SIZE_MAX
|| uncompressed_size > LZMA_VLI_MAX)
return LZMA_PROG_ERROR;
- s = (index_stream *)(i->streams.rightmost);
- g = (index_group *)(s->groups.rightmost);
+ index_stream *s = (index_stream *)(i->streams.rightmost);
+ index_group *g = (index_group *)(s->groups.rightmost);
- compressed_base = g == NULL ? 0
+ const lzma_vli compressed_base = g == NULL ? 0
: vli_ceil4(g->records[g->last].unpadded_sum);
- uncompressed_base = g == NULL ? 0
+ const lzma_vli uncompressed_base = g == NULL ? 0
: g->records[g->last].uncompressed_sum;
- index_list_size_add = lzma_vli_size(unpadded_size)
+ const uint32_t index_list_size_add = lzma_vli_size(unpadded_size)
+ lzma_vli_size(uncompressed_size);
// Check that the file size will stay within limits.
@@ -780,10 +764,9 @@ index_cat_helper(const index_cat_info *info, index_stream *this)
extern LZMA_API(lzma_ret)
-lzma_index_cat(lzma_index *LZMA_RESTRICT dest, lzma_index *LZMA_RESTRICT src,
- lzma_allocator *allocator)
+lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
+ const lzma_allocator *allocator)
{
- index_cat_info info;
const lzma_vli dest_file_size = lzma_index_file_size(dest);
// Check that we don't exceed the file size limits.
@@ -813,12 +796,10 @@ lzma_index_cat(lzma_index *LZMA_RESTRICT dest, lzma_index *LZMA_RESTRICT src,
index_stream *s = (index_stream *)(dest->streams.rightmost);
index_group *g = (index_group *)(s->groups.rightmost);
if (g != NULL && g->last + 1 < g->allocated) {
- index_group *newg;
-
assert(g->node.left == NULL);
assert(g->node.right == NULL);
- newg = lzma_alloc(sizeof(index_group)
+ index_group *newg = lzma_alloc(sizeof(index_group)
+ (g->last + 1)
* sizeof(index_record),
allocator);
@@ -848,17 +829,21 @@ lzma_index_cat(lzma_index *LZMA_RESTRICT dest, lzma_index *LZMA_RESTRICT src,
s->groups.rightmost = &newg->node;
lzma_free(g, allocator);
+
+ // NOTE: newg isn't leaked here because
+ // newg == (void *)&newg->node.
}
}
// Add all the Streams from src to dest. Update the base offsets
// of each Stream from src.
- info.uncompressed_size = dest->uncompressed_size;
- info.file_size = dest_file_size;
- info.stream_number_add = dest->streams.count;
- info.block_number_add = dest->record_count;
- info.streams = &dest->streams;
-
+ const index_cat_info info = {
+ .uncompressed_size = dest->uncompressed_size,
+ .file_size = dest_file_size,
+ .stream_number_add = dest->streams.count,
+ .block_number_add = dest->record_count,
+ .streams = &dest->streams,
+ };
index_cat_helper(&info, (index_stream *)(src->streams.root));
// Update info about all the combined Streams.
@@ -877,26 +862,18 @@ lzma_index_cat(lzma_index *LZMA_RESTRICT dest, lzma_index *LZMA_RESTRICT src,
/// Duplicate an index_stream.
static index_stream *
-index_dup_stream(const index_stream *src, lzma_allocator *allocator)
+index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
{
- index_stream *dest;
- index_group *destg;
- index_group *srcg;
- size_t i = 0;
-
// Catch a somewhat theoretical integer overflow.
if (src->record_count > PREALLOC_MAX)
return NULL;
// Allocate and initialize a new Stream.
- dest = index_stream_init(src->node.compressed_base,
+ index_stream *dest = index_stream_init(src->node.compressed_base,
src->node.uncompressed_base, src->number,
src->block_number_base, allocator);
-
- // Return immediately if allocation failed or if there are
- // no groups to duplicate.
- if (dest == NULL || src->groups.leftmost == NULL)
- return dest;
+ if (dest == NULL)
+ return NULL;
// Copy the overall information.
dest->record_count = src->record_count;
@@ -904,10 +881,14 @@ index_dup_stream(const index_stream *src, lzma_allocator *allocator)
dest->stream_flags = src->stream_flags;
dest->stream_padding = src->stream_padding;
+ // Return if there are no groups to duplicate.
+ if (src->groups.leftmost == NULL)
+ return dest;
+
// Allocate memory for the Records. We put all the Records into
// a single group. It's simplest and also tends to make
// lzma_index_locate() a little bit faster with very big Indexes.
- destg = lzma_alloc(sizeof(index_group)
+ index_group *destg = lzma_alloc(sizeof(index_group)
+ src->record_count * sizeof(index_record),
allocator);
if (destg == NULL) {
@@ -923,7 +904,8 @@ index_dup_stream(const index_stream *src, lzma_allocator *allocator)
destg->last = src->record_count - 1;
// Go through all the groups in src and copy the Records into destg.
- srcg = (index_group *)(src->groups.leftmost);
+ const index_group *srcg = (const index_group *)(src->groups.leftmost);
+ size_t i = 0;
do {
memcpy(destg->records + i, srcg->records,
(srcg->last + 1) * sizeof(index_record));
@@ -941,11 +923,8 @@ index_dup_stream(const index_stream *src, lzma_allocator *allocator)
extern LZMA_API(lzma_index *)
-lzma_index_dup(const lzma_index *src, lzma_allocator *allocator)
+lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator)
{
- index_stream *srcstream;
- index_stream *deststream;
-
// Allocate the base structure (no initial Stream).
lzma_index *dest = index_init_plain(allocator);
if (dest == NULL)
@@ -958,9 +937,11 @@ lzma_index_dup(const lzma_index *src, lzma_allocator *allocator)
dest->index_list_size = src->index_list_size;
// Copy the Streams and the groups in them.
- srcstream = (index_stream *)(src->streams.leftmost);
+ const index_stream *srcstream
+ = (const index_stream *)(src->streams.leftmost);
do {
- deststream = index_dup_stream(srcstream, allocator);
+ index_stream *deststream = index_dup_stream(
+ srcstream, allocator);
if (deststream == NULL) {
lzma_index_end(dest, allocator);
return NULL;
@@ -1031,6 +1012,8 @@ iter_set_info(lzma_index_iter *iter)
iter->internal[ITER_GROUP].p = NULL;
}
+ // NOTE: lzma_index_iter.stream.number is lzma_vli but we use uint32_t
+ // internally.
iter->stream.number = stream->number;
iter->stream.block_count = stream->record_count;
iter->stream.compressed_offset = stream->node.compressed_base;
@@ -1119,19 +1102,14 @@ lzma_index_iter_rewind(lzma_index_iter *iter)
extern LZMA_API(lzma_bool)
lzma_index_iter_next(lzma_index_iter *iter, lzma_index_iter_mode mode)
{
- const lzma_index *i;
- const index_stream *stream;
- const index_group *group;
- size_t record;
-
// Catch unsupported mode values.
if ((unsigned int)(mode) > LZMA_INDEX_ITER_NONEMPTY_BLOCK)
return true;
- i = iter->internal[ITER_INDEX].p;
- stream = iter->internal[ITER_STREAM].p;
- group = NULL;
- record = iter->internal[ITER_RECORD].s;
+ const lzma_index *i = iter->internal[ITER_INDEX].p;
+ const index_stream *stream = iter->internal[ITER_STREAM].p;
+ const index_group *group = NULL;
+ size_t record = iter->internal[ITER_RECORD].s;
// If we are being asked for the next Stream, leave group to NULL
// so that the rest of the this function thinks that this Stream
@@ -1231,10 +1209,6 @@ again:
extern LZMA_API(lzma_bool)
lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
{
- const index_stream *stream;
- const index_group *group;
- size_t left, right;
-
const lzma_index *i = iter->internal[ITER_INDEX].p;
// If the target is past the end of the file, return immediately.
@@ -1242,12 +1216,12 @@ lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
return true;
// Locate the Stream containing the target offset.
- stream = index_tree_locate(&i->streams, target);
+ const index_stream *stream = index_tree_locate(&i->streams, target);
assert(stream != NULL);
target -= stream->node.uncompressed_base;
// Locate the group containing the target offset.
- group = index_tree_locate(&stream->groups, target);
+ const index_group *group = index_tree_locate(&stream->groups, target);
assert(group != NULL);
// Use binary search to locate the exact Record. It is the first
@@ -1255,8 +1229,8 @@ lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
// This is because we want the rightmost Record that fullfills the
// search criterion. It is possible that there are empty Blocks;
// we don't want to return them.
- left = 0;
- right = group->last;
+ size_t left = 0;
+ size_t right = group->last;
while (left < right) {
const size_t pos = left + (right - left) / 2;
diff --git a/Utilities/cmliblzma/liblzma/common/index_decoder.c b/Utilities/cmliblzma/liblzma/common/index_decoder.c
index 943cfd58a..cc07a1b8c 100644
--- a/Utilities/cmliblzma/liblzma/common/index_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/index_decoder.c
@@ -14,7 +14,7 @@
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_INDICATOR,
SEQ_COUNT,
@@ -50,18 +50,20 @@ struct lzma_coder_s {
/// CRC32 of the List of Records field
uint32_t crc32;
-};
+} lzma_index_coder;
static lzma_ret
-index_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+index_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size,
- uint8_t *LZMA_RESTRICT out lzma_attribute((__unused__)),
- size_t *LZMA_RESTRICT out_pos lzma_attribute((__unused__)),
+ uint8_t *restrict out lzma_attribute((__unused__)),
+ size_t *restrict out_pos lzma_attribute((__unused__)),
size_t out_size lzma_attribute((__unused__)),
lzma_action action lzma_attribute((__unused__)))
{
+ lzma_index_coder *coder = coder_ptr;
+
// Similar optimization as in index_encoder.c
const size_t in_start = *in_pos;
lzma_ret ret = LZMA_OK;
@@ -207,8 +209,9 @@ out:
static void
-index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+index_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_index_coder *coder = coder_ptr;
lzma_index_end(coder->index, allocator);
lzma_free(coder, allocator);
return;
@@ -216,9 +219,11 @@ index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_index_coder *coder = coder_ptr;
+
*memusage = lzma_index_memusage(1, coder->count);
*old_memlimit = coder->memlimit;
@@ -234,7 +239,7 @@ index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
static lzma_ret
-index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
+index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
lzma_index **i, uint64_t memlimit)
{
// Remember the pointer given by the application. We will set it
@@ -251,7 +256,7 @@ index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
// Initialize the rest.
coder->sequence = SEQ_INDICATOR;
- coder->memlimit = memlimit;
+ coder->memlimit = my_max(1, memlimit);
coder->count = 0; // Needs to be initialized due to _memconfig().
coder->pos = 0;
coder->crc32 = 0;
@@ -261,35 +266,37 @@ index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
static lzma_ret
-index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
lzma_index **i, uint64_t memlimit)
{
lzma_next_coder_init(&index_decoder_init, next, allocator);
- if (i == NULL || memlimit == 0)
+ if (i == NULL)
return LZMA_PROG_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_index_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &index_decode;
next->end = &index_decoder_end;
next->memconfig = &index_decoder_memconfig;
- next->coder->index = NULL;
+ coder->index = NULL;
} else {
- lzma_index_end(next->coder->index, allocator);
+ lzma_index_end(coder->index, allocator);
}
- return index_decoder_reset(next->coder, allocator, i, memlimit);
+ return index_decoder_reset(coder, allocator, i, memlimit);
}
extern LZMA_API(lzma_ret)
lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
{
- lzma_next_strm_init2(index_decoder_init, strm, i, memlimit);
+ lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
@@ -299,27 +306,25 @@ lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
extern LZMA_API(lzma_ret)
-lzma_index_buffer_decode(
- lzma_index **i, uint64_t *memlimit, lzma_allocator *allocator,
+lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
+ const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
{
- lzma_coder coder;
- lzma_ret ret;
-
- // Store the input start position so that we can restore it in case
- // of an error.
- const size_t in_start = *in_pos;
-
// Sanity checks
if (i == NULL || memlimit == NULL
|| in == NULL || in_pos == NULL || *in_pos > in_size)
return LZMA_PROG_ERROR;
// Initialize the decoder.
+ lzma_index_coder coder;
return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
+ // Store the input start position so that we can restore it in case
+ // of an error.
+ const size_t in_start = *in_pos;
+
// Do the actual decoding.
- ret = index_decode(&coder, allocator, in, in_pos, in_size,
+ lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
NULL, NULL, 0, LZMA_RUN);
if (ret == LZMA_STREAM_END) {
diff --git a/Utilities/cmliblzma/liblzma/common/index_encoder.c b/Utilities/cmliblzma/liblzma/common/index_encoder.c
index 194bf2113..ac97d0ceb 100644
--- a/Utilities/cmliblzma/liblzma/common/index_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/index_encoder.c
@@ -15,7 +15,7 @@
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_INDICATOR,
SEQ_COUNT,
@@ -37,19 +37,21 @@ struct lzma_coder_s {
/// CRC32 of the List of Records field
uint32_t crc32;
-};
+} lzma_index_coder;
static lzma_ret
-index_encode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in lzma_attribute((__unused__)),
- size_t *LZMA_RESTRICT in_pos lzma_attribute((__unused__)),
+index_encode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in lzma_attribute((__unused__)),
+ size_t *restrict in_pos lzma_attribute((__unused__)),
size_t in_size lzma_attribute((__unused__)),
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size,
lzma_action action lzma_attribute((__unused__)))
{
+ lzma_index_coder *coder = coder_ptr;
+
// Position where to start calculating CRC32. The idea is that we
// need to call lzma_crc32() only once per call to index_encode().
const size_t out_start = *out_pos;
@@ -159,7 +161,7 @@ out:
static void
-index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+index_encoder_end(void *coder, const lzma_allocator *allocator)
{
lzma_free(coder, allocator);
return;
@@ -167,7 +169,7 @@ index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
static void
-index_encoder_reset(lzma_coder *coder, const lzma_index *i)
+index_encoder_reset(lzma_index_coder *coder, const lzma_index *i)
{
lzma_index_iter_init(&coder->iter, i);
@@ -181,7 +183,7 @@ index_encoder_reset(lzma_coder *coder, const lzma_index *i)
extern lzma_ret
-lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_index *i)
{
lzma_next_coder_init(&lzma_index_encoder_init, next, allocator);
@@ -190,7 +192,7 @@ lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
return LZMA_PROG_ERROR;
if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ next->coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
if (next->coder == NULL)
return LZMA_MEM_ERROR;
@@ -207,7 +209,7 @@ lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API(lzma_ret)
lzma_index_encoder(lzma_stream *strm, const lzma_index *i)
{
- lzma_next_strm_init1(lzma_index_encoder_init, strm, i);
+ lzma_next_strm_init(lzma_index_encoder_init, strm, i);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
@@ -220,10 +222,6 @@ extern LZMA_API(lzma_ret)
lzma_index_buffer_encode(const lzma_index *i,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_coder coder;
- size_t out_start;
- lzma_ret ret;
-
// Validate the arguments.
if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size)
return LZMA_PROG_ERROR;
@@ -234,12 +232,13 @@ lzma_index_buffer_encode(const lzma_index *i,
// The Index encoder needs just one small data structure so we can
// allocate it on stack.
+ lzma_index_coder coder;
index_encoder_reset(&coder, i);
// Do the actual encoding. This should never fail, but store
// the original *out_pos just in case.
- out_start = *out_pos;
- ret = index_encode(&coder, NULL, NULL, NULL, 0,
+ const size_t out_start = *out_pos;
+ lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
out, out_pos, out_size, LZMA_RUN);
if (ret == LZMA_STREAM_END) {
diff --git a/Utilities/cmliblzma/liblzma/common/index_encoder.h b/Utilities/cmliblzma/liblzma/common/index_encoder.h
index a13c94dcd..4d55cd104 100644
--- a/Utilities/cmliblzma/liblzma/common/index_encoder.h
+++ b/Utilities/cmliblzma/liblzma/common/index_encoder.h
@@ -17,7 +17,7 @@
extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_index *i);
+ const lzma_allocator *allocator, const lzma_index *i);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/index_hash.c b/Utilities/cmliblzma/liblzma/common/index_hash.c
index 0cf86b307..d7a0344b7 100644
--- a/Utilities/cmliblzma/liblzma/common/index_hash.c
+++ b/Utilities/cmliblzma/liblzma/common/index_hash.c
@@ -70,7 +70,8 @@ struct lzma_index_hash_s {
extern LZMA_API(lzma_index_hash *)
-lzma_index_hash_init(lzma_index_hash *index_hash, lzma_allocator *allocator)
+lzma_index_hash_init(lzma_index_hash *index_hash,
+ const lzma_allocator *allocator)
{
if (index_hash == NULL) {
index_hash = lzma_alloc(sizeof(lzma_index_hash), allocator);
@@ -101,7 +102,8 @@ lzma_index_hash_init(lzma_index_hash *index_hash, lzma_allocator *allocator)
extern LZMA_API(void)
-lzma_index_hash_end(lzma_index_hash *index_hash, lzma_allocator *allocator)
+lzma_index_hash_end(lzma_index_hash *index_hash,
+ const lzma_allocator *allocator)
{
lzma_free(index_hash, allocator);
return;
@@ -124,14 +126,13 @@ static lzma_ret
hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
lzma_vli uncompressed_size)
{
- const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
-
info->blocks_size += vli_ceil4(unpadded_size);
info->uncompressed_size += uncompressed_size;
info->index_list_size += lzma_vli_size(unpadded_size)
+ lzma_vli_size(uncompressed_size);
++info->count;
+ const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
lzma_check_update(&info->check, LZMA_CHECK_BEST,
(const uint8_t *)(sizes), sizeof(sizes));
@@ -174,9 +175,6 @@ extern LZMA_API(lzma_ret)
lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
size_t *in_pos, size_t in_size)
{
- size_t in_start;
- lzma_ret ret;
-
// Catch zero input buffer here, because in contrast to Index encoder
// and decoder functions, applications call this function directly
// instead of via lzma_code(), which does the buffer checking.
@@ -186,8 +184,8 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
// NOTE: This function has many similarities to index_encode() and
// index_decode() functions found from index_encoder.c and
// index_decoder.c. See the comments especially in index_encoder.c.
- in_start = *in_pos;
- ret = LZMA_OK;
+ const size_t in_start = *in_pos;
+ lzma_ret ret = LZMA_OK;
while (*in_pos < in_size)
switch (index_hash->sequence) {
diff --git a/Utilities/cmliblzma/liblzma/common/memcmplen.h b/Utilities/cmliblzma/liblzma/common/memcmplen.h
new file mode 100644
index 000000000..c1efc9e28
--- /dev/null
+++ b/Utilities/cmliblzma/liblzma/common/memcmplen.h
@@ -0,0 +1,175 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file memcmplen.h
+/// \brief Optimized comparison of two buffers
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_MEMCMPLEN_H
+#define LZMA_MEMCMPLEN_H
+
+#include "common.h"
+
+#ifdef HAVE_IMMINTRIN_H
+# include <immintrin.h>
+#endif
+
+
+/// Find out how many equal bytes the two buffers have.
+///
+/// \param buf1 First buffer
+/// \param buf2 Second buffer
+/// \param len How many bytes have already been compared and will
+/// be assumed to match
+/// \param limit How many bytes to compare at most, including the
+/// already-compared bytes. This must be significantly
+/// smaller than UINT32_MAX to avoid integer overflows.
+/// Up to LZMA_MEMCMPLEN_EXTRA bytes may be read past
+/// the specified limit from both buf1 and buf2.
+///
+/// \return Number of equal bytes in the buffers is returned.
+/// This is always at least len and at most limit.
+///
+/// \note LZMA_MEMCMPLEN_EXTRA defines how many extra bytes may be read.
+/// It's rounded up to 2^n. This extra amount needs to be
+/// allocated in the buffers being used. It needs to be
+/// initialized too to keep Valgrind quiet.
+static inline uint32_t lzma_attribute((__always_inline__))
+lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
+ uint32_t len, uint32_t limit)
+{
+ assert(len <= limit);
+ assert(limit <= UINT32_MAX / 2);
+
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && ((TUKLIB_GNUC_REQ(3, 4) && defined(__x86_64__)) \
+ || (defined(__INTEL_COMPILER) && defined(__x86_64__)) \
+ || (defined(__INTEL_COMPILER) && defined(_M_X64)) \
+ || (defined(_MSC_VER) && defined(_M_X64)))
+ // NOTE: This will use 64-bit unaligned access which
+ // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit, but
+ // it's convenient here at least as long as it's x86-64 only.
+ //
+ // I keep this x86-64 only for now since that's where I know this
+ // to be a good method. This may be fine on other 64-bit CPUs too.
+ // On big endian one should use xor instead of subtraction and switch
+ // to __builtin_clzll().
+#define LZMA_MEMCMPLEN_EXTRA 8
+ while (len < limit) {
+ const uint64_t x = *(const uint64_t *)(buf1 + len)
+ - *(const uint64_t *)(buf2 + len);
+ if (x != 0) {
+# if defined(_M_X64) // MSVC or Intel C compiler on Windows
+ unsigned long tmp;
+ _BitScanForward64(&tmp, x);
+ len += (uint32_t)tmp >> 3;
+# else // GCC, clang, or Intel C compiler
+ len += (uint32_t)__builtin_ctzll(x) >> 3;
+# endif
+ return my_min(len, limit);
+ }
+
+ len += 8;
+ }
+
+ return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(HAVE__MM_MOVEMASK_EPI8) \
+ && ((defined(__GNUC__) && defined(__SSE2_MATH__)) \
+ || (defined(__INTEL_COMPILER) && defined(__SSE2__)) \
+ || (defined(_MSC_VER) && defined(_M_IX86_FP) \
+ && _M_IX86_FP >= 2))
+ // NOTE: Like above, this will use 128-bit unaligned access which
+ // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit.
+ //
+ // SSE2 version for 32-bit and 64-bit x86. On x86-64 the above
+ // version is sometimes significantly faster and sometimes
+ // slightly slower than this SSE2 version, so this SSE2
+ // version isn't used on x86-64.
+# define LZMA_MEMCMPLEN_EXTRA 16
+ while (len < limit) {
+ const uint32_t x = 0xFFFF ^ _mm_movemask_epi8(_mm_cmpeq_epi8(
+ _mm_loadu_si128((const __m128i *)(buf1 + len)),
+ _mm_loadu_si128((const __m128i *)(buf2 + len))));
+
+ if (x != 0) {
+# if defined(__INTEL_COMPILER)
+ len += _bit_scan_forward(x);
+# elif defined(_MSC_VER)
+ unsigned long tmp;
+ _BitScanForward(&tmp, x);
+ len += tmp;
+# else
+ len += __builtin_ctz(x);
+# endif
+ return my_min(len, limit);
+ }
+
+ len += 16;
+ }
+
+ return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && !defined(WORDS_BIGENDIAN)
+ // Generic 32-bit little endian method
+# define LZMA_MEMCMPLEN_EXTRA 4
+ while (len < limit) {
+ uint32_t x = *(const uint32_t *)(buf1 + len)
+ - *(const uint32_t *)(buf2 + len);
+ if (x != 0) {
+ if ((x & 0xFFFF) == 0) {
+ len += 2;
+ x >>= 16;
+ }
+
+ if ((x & 0xFF) == 0)
+ ++len;
+
+ return my_min(len, limit);
+ }
+
+ len += 4;
+ }
+
+ return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && defined(WORDS_BIGENDIAN)
+ // Generic 32-bit big endian method
+# define LZMA_MEMCMPLEN_EXTRA 4
+ while (len < limit) {
+ uint32_t x = *(const uint32_t *)(buf1 + len)
+ ^ *(const uint32_t *)(buf2 + len);
+ if (x != 0) {
+ if ((x & 0xFFFF0000) == 0) {
+ len += 2;
+ x <<= 16;
+ }
+
+ if ((x & 0xFF000000) == 0)
+ ++len;
+
+ return my_min(len, limit);
+ }
+
+ len += 4;
+ }
+
+ return limit;
+
+#else
+ // Simple portable version that doesn't use unaligned access.
+# define LZMA_MEMCMPLEN_EXTRA 0
+ while (len < limit && buf1[len] == buf2[len])
+ ++len;
+
+ return len;
+#endif
+}
+
+#endif
diff --git a/Utilities/cmliblzma/liblzma/common/outqueue.c b/Utilities/cmliblzma/liblzma/common/outqueue.c
new file mode 100644
index 000000000..2dc8a38d1
--- /dev/null
+++ b/Utilities/cmliblzma/liblzma/common/outqueue.c
@@ -0,0 +1,184 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file outqueue.c
+/// \brief Output queue handling in multithreaded coding
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "outqueue.h"
+
+
+/// This is to ease integer overflow checking: We may allocate up to
+/// 2 * LZMA_THREADS_MAX buffers and we need some extra memory for other
+/// data structures (that's the second /2).
+#define BUF_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX / 2 / 2)
+
+
+static lzma_ret
+get_options(uint64_t *bufs_alloc_size, uint32_t *bufs_count,
+ uint64_t buf_size_max, uint32_t threads)
+{
+ if (threads > LZMA_THREADS_MAX || buf_size_max > BUF_SIZE_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ // The number of buffers is twice the number of threads.
+ // This wastes RAM but keeps the threads busy when buffers
+ // finish out of order.
+ //
+ // NOTE: If this is changed, update BUF_SIZE_MAX too.
+ *bufs_count = threads * 2;
+ *bufs_alloc_size = *bufs_count * buf_size_max;
+
+ return LZMA_OK;
+}
+
+
+extern uint64_t
+lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads)
+{
+ uint64_t bufs_alloc_size;
+ uint32_t bufs_count;
+
+ if (get_options(&bufs_alloc_size, &bufs_count, buf_size_max, threads)
+ != LZMA_OK)
+ return UINT64_MAX;
+
+ return sizeof(lzma_outq) + bufs_count * sizeof(lzma_outbuf)
+ + bufs_alloc_size;
+}
+
+
+extern lzma_ret
+lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
+ uint64_t buf_size_max, uint32_t threads)
+{
+ uint64_t bufs_alloc_size;
+ uint32_t bufs_count;
+
+ // Set bufs_count and bufs_alloc_size.
+ return_if_error(get_options(&bufs_alloc_size, &bufs_count,
+ buf_size_max, threads));
+
+ // Allocate memory if needed.
+ if (outq->buf_size_max != buf_size_max
+ || outq->bufs_allocated != bufs_count) {
+ lzma_outq_end(outq, allocator);
+
+#if SIZE_MAX < UINT64_MAX
+ if (bufs_alloc_size > SIZE_MAX)
+ return LZMA_MEM_ERROR;
+#endif
+
+ outq->bufs = lzma_alloc(bufs_count * sizeof(lzma_outbuf),
+ allocator);
+ outq->bufs_mem = lzma_alloc((size_t)(bufs_alloc_size),
+ allocator);
+
+ if (outq->bufs == NULL || outq->bufs_mem == NULL) {
+ lzma_outq_end(outq, allocator);
+ return LZMA_MEM_ERROR;
+ }
+ }
+
+ // Initialize the rest of the main structure. Initialization of
+ // outq->bufs[] is done when they are actually needed.
+ outq->buf_size_max = (size_t)(buf_size_max);
+ outq->bufs_allocated = bufs_count;
+ outq->bufs_pos = 0;
+ outq->bufs_used = 0;
+ outq->read_pos = 0;
+
+ return LZMA_OK;
+}
+
+
+extern void
+lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator)
+{
+ lzma_free(outq->bufs, allocator);
+ outq->bufs = NULL;
+
+ lzma_free(outq->bufs_mem, allocator);
+ outq->bufs_mem = NULL;
+
+ return;
+}
+
+
+extern lzma_outbuf *
+lzma_outq_get_buf(lzma_outq *outq)
+{
+ // Caller must have checked it with lzma_outq_has_buf().
+ assert(outq->bufs_used < outq->bufs_allocated);
+
+ // Initialize the new buffer.
+ lzma_outbuf *buf = &outq->bufs[outq->bufs_pos];
+ buf->buf = outq->bufs_mem + outq->bufs_pos * outq->buf_size_max;
+ buf->size = 0;
+ buf->finished = false;
+
+ // Update the queue state.
+ if (++outq->bufs_pos == outq->bufs_allocated)
+ outq->bufs_pos = 0;
+
+ ++outq->bufs_used;
+
+ return buf;
+}
+
+
+extern bool
+lzma_outq_is_readable(const lzma_outq *outq)
+{
+ uint32_t i = outq->bufs_pos - outq->bufs_used;
+ if (outq->bufs_pos < outq->bufs_used)
+ i += outq->bufs_allocated;
+
+ return outq->bufs[i].finished;
+}
+
+
+extern lzma_ret
+lzma_outq_read(lzma_outq *restrict outq, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
+ lzma_vli *restrict unpadded_size,
+ lzma_vli *restrict uncompressed_size)
+{
+ // There must be at least one buffer from which to read.
+ if (outq->bufs_used == 0)
+ return LZMA_OK;
+
+ // Get the buffer.
+ uint32_t i = outq->bufs_pos - outq->bufs_used;
+ if (outq->bufs_pos < outq->bufs_used)
+ i += outq->bufs_allocated;
+
+ lzma_outbuf *buf = &outq->bufs[i];
+
+ // If it isn't finished yet, we cannot read from it.
+ if (!buf->finished)
+ return LZMA_OK;
+
+ // Copy from the buffer to output.
+ lzma_bufcpy(buf->buf, &outq->read_pos, buf->size,
+ out, out_pos, out_size);
+
+ // Return if we didn't get all the data from the buffer.
+ if (outq->read_pos < buf->size)
+ return LZMA_OK;
+
+ // The buffer was finished. Tell the caller its size information.
+ *unpadded_size = buf->unpadded_size;
+ *uncompressed_size = buf->uncompressed_size;
+
+ // Free this buffer for further use.
+ --outq->bufs_used;
+ outq->read_pos = 0;
+
+ return LZMA_STREAM_END;
+}
diff --git a/Utilities/cmliblzma/liblzma/common/outqueue.h b/Utilities/cmliblzma/liblzma/common/outqueue.h
new file mode 100644
index 000000000..079634de4
--- /dev/null
+++ b/Utilities/cmliblzma/liblzma/common/outqueue.h
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file outqueue.h
+/// \brief Output queue handling in multithreaded coding
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+/// Output buffer for a single thread
+typedef struct {
+ /// Pointer to the output buffer of lzma_outq.buf_size_max bytes
+ uint8_t *buf;
+
+ /// Amount of data written to buf
+ size_t size;
+
+ /// Additional size information
+ lzma_vli unpadded_size;
+ lzma_vli uncompressed_size;
+
+ /// True when no more data will be written into this buffer.
+ ///
+ /// \note This is read by another thread and thus access
+ /// to this variable needs a mutex.
+ bool finished;
+
+} lzma_outbuf;
+
+
+typedef struct {
+ /// Array of buffers that are used cyclically.
+ lzma_outbuf *bufs;
+
+ /// Memory allocated for all the buffers
+ uint8_t *bufs_mem;
+
+ /// Amount of buffer space available in each buffer
+ size_t buf_size_max;
+
+ /// Number of buffers allocated
+ uint32_t bufs_allocated;
+
+ /// Position in the bufs array. The next buffer to be taken
+ /// into use is bufs[bufs_pos].
+ uint32_t bufs_pos;
+
+ /// Number of buffers in use
+ uint32_t bufs_used;
+
+ /// Position in the buffer in lzma_outq_read()
+ size_t read_pos;
+
+} lzma_outq;
+
+
+/**
+ * \brief Calculate the memory usage of an output queue
+ *
+ * \return Approximate memory usage in bytes or UINT64_MAX on error.
+ */
+extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief Initialize an output queue
+///
+/// \param outq Pointer to an output queue. Before calling
+/// this function the first time, *outq should
+/// have been zeroed with memzero() so that this
+/// function knows that there are no previous
+/// allocations to free.
+/// \param allocator Pointer to allocator or NULL
+/// \param buf_size_max Maximum amount of data that a single buffer
+/// in the queue may need to store.
+/// \param threads Number of buffers that may be in use
+/// concurrently. Note that more than this number
+/// of buffers will actually get allocated to
+/// improve performance when buffers finish
+/// out of order.
+///
+/// \return - LZMA_OK
+/// - LZMA_MEM_ERROR
+///
+extern lzma_ret lzma_outq_init(
+ lzma_outq *outq, const lzma_allocator *allocator,
+ uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief Free the memory associated with the output queue
+extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
+
+
+/// \brief Get a new buffer
+///
+/// lzma_outq_has_buf() must be used to check that there is a buffer
+/// available before calling lzma_outq_get_buf().
+///
+extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
+
+
+/// \brief Test if there is data ready to be read
+///
+/// Call to this function must be protected with the same mutex that
+/// is used to protect lzma_outbuf.finished.
+///
+extern bool lzma_outq_is_readable(const lzma_outq *outq);
+
+
+/// \brief Read finished data
+///
+/// \param outq Pointer to an output queue
+/// \param out Beginning of the output buffer
+/// \param out_pos The next byte will be written to
+/// out[*out_pos].
+/// \param out_size Size of the out buffer; the first byte into
+/// which no data is written to is out[out_size].
+/// \param unpadded_size Unpadded Size from the Block encoder
+/// \param uncompressed_size Uncompressed Size from the Block encoder
+///
+/// \return - LZMA: All OK. Either no data was available or the buffer
+/// being read didn't become empty yet.
+/// - LZMA_STREAM_END: The buffer being read was finished.
+/// *unpadded_size and *uncompressed_size were set.
+///
+/// \note This reads lzma_outbuf.finished variables and thus call
+/// to this function needs to be protected with a mutex.
+///
+extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
+ uint8_t *restrict out, size_t *restrict out_pos,
+ size_t out_size, lzma_vli *restrict unpadded_size,
+ lzma_vli *restrict uncompressed_size);
+
+
+/// \brief Test if there is at least one buffer free
+///
+/// This must be used before getting a new buffer with lzma_outq_get_buf().
+///
+static inline bool
+lzma_outq_has_buf(const lzma_outq *outq)
+{
+ return outq->bufs_used < outq->bufs_allocated;
+}
+
+
+/// \brief Test if the queue is completely empty
+static inline bool
+lzma_outq_is_empty(const lzma_outq *outq)
+{
+ return outq->bufs_used == 0;
+}
diff --git a/Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c b/Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c
index 9e2e1da83..b9745b5db 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c
@@ -15,13 +15,10 @@
extern LZMA_API(lzma_ret)
lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
- lzma_allocator *allocator,
+ const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
- lzma_ret ret;
-
// Sanity checks
if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|| *in_pos > in_size || out_pos == NULL
@@ -36,7 +33,8 @@ lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
// Initialize the Stream decoder.
// TODO: We need something to tell the decoder that it can use the
// output buffer as workspace, and thus save significant amount of RAM.
- ret = lzma_stream_decoder_init(
+ lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
+ lzma_ret ret = lzma_stream_decoder_init(
&stream_decoder, allocator, *memlimit, flags);
if (ret == LZMA_OK) {
diff --git a/Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c b/Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c
index 8bca87f47..af49554a6 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c
@@ -42,13 +42,10 @@ lzma_stream_buffer_bound(size_t uncompressed_size)
extern LZMA_API(lzma_ret)
lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+ const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos_ptr, size_t out_size)
{
- lzma_stream_flags stream_flags = { 0 };
- lzma_block block = { 0 };
- size_t out_pos;
-
// Sanity checks
if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX
|| (in == NULL && in_size != 0) || out == NULL
@@ -65,7 +62,7 @@ lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
// Use a local copy. We update *out_pos_ptr only if everything
// succeeds.
- out_pos = *out_pos_ptr;
+ size_t out_pos = *out_pos_ptr;
// Check that there's enough space for both Stream Header and
// Stream Footer.
@@ -77,7 +74,10 @@ lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
out_size -= LZMA_STREAM_HEADER_SIZE;
// Encode the Stream Header.
- stream_flags.check = check;
+ lzma_stream_flags stream_flags = {
+ .version = 0,
+ .check = check,
+ };
if (lzma_stream_header_encode(&stream_flags, out + out_pos)
!= LZMA_OK)
@@ -86,8 +86,11 @@ lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
out_pos += LZMA_STREAM_HEADER_SIZE;
// Encode a Block but only if there is at least one byte of input.
- block.check = check;
- block.filters = filters;
+ lzma_block block = {
+ .version = 0,
+ .check = check,
+ .filters = filters,
+ };
if (in_size > 0)
return_if_error(lzma_block_buffer_encode(&block, allocator,
@@ -95,8 +98,6 @@ lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
// Index
{
- lzma_ret ret;
-
// Create an Index. It will have one Record if there was
// at least one byte of input to encode. Otherwise the
// Index will be empty.
@@ -104,7 +105,7 @@ lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
if (i == NULL)
return LZMA_MEM_ERROR;
- ret = LZMA_OK;
+ lzma_ret ret = LZMA_OK;
if (in_size > 0)
ret = lzma_index_append(i, allocator,
diff --git a/Utilities/cmliblzma/liblzma/common/stream_decoder.c b/Utilities/cmliblzma/liblzma/common/stream_decoder.c
index 5e9a22069..fdd8ff2f9 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_decoder.c
@@ -14,7 +14,7 @@
#include "block_decoder.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_STREAM_HEADER,
SEQ_BLOCK_HEADER,
@@ -57,6 +57,10 @@ struct lzma_coder_s {
/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
bool tell_any_check;
+ /// If true, we will tell the Block decoder to skip calculating
+ /// and verifying the integrity check.
+ bool ignore_check;
+
/// If true, we will decode concatenated Streams that possibly have
/// Stream Padding between or after them. LZMA_STREAM_END is returned
/// once the application isn't giving us any new input, and we aren't
@@ -76,11 +80,11 @@ struct lzma_coder_s {
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
/// Block Header has biggest maximum size.
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
-};
+} lzma_stream_coder;
static lzma_ret
-stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
+stream_decoder_reset(lzma_stream_coder *coder, const lzma_allocator *allocator)
{
// Initialize the Index hash used to verify the Index.
coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
@@ -96,18 +100,18 @@ stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-stream_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+stream_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_stream_coder *coder = coder_ptr;
+
// When decoding the actual Block, it may be able to produce more
// output even if we don't give it any new input.
while (true)
switch (coder->sequence) {
case SEQ_STREAM_HEADER: {
- lzma_ret ret;
-
// Copy the Stream Header to the internal buffer.
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE);
@@ -119,7 +123,7 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->pos = 0;
// Decode the Stream Header.
- ret = lzma_stream_header_decode(
+ const lzma_ret ret = lzma_stream_header_decode(
&coder->stream_flags, coder->buffer);
if (ret != LZMA_OK)
return ret == LZMA_FORMAT_ERROR && !coder->first_stream
@@ -156,11 +160,6 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through
case SEQ_BLOCK_HEADER: {
- lzma_filter filters[LZMA_FILTERS_MAX + 1];
- uint64_t memusage;
- lzma_ret ret;
- size_t i;
-
if (*in_pos >= in_size)
return LZMA_OK;
@@ -189,20 +188,28 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->pos = 0;
- // Version 0 is currently the only possible version.
- coder->block_options.version = 0;
+ // Version 1 is needed to support the .ignore_check option.
+ coder->block_options.version = 1;
// Set up a buffer to hold the filter chain. Block Header
// decoder will initialize all members of this array so
// we don't need to do it here.
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
coder->block_options.filters = filters;
// Decode the Block Header.
return_if_error(lzma_block_header_decode(&coder->block_options,
allocator, coder->buffer));
+ // If LZMA_IGNORE_CHECK was used, this flag needs to be set.
+ // It has to be set after lzma_block_header_decode() because
+ // it always resets this to false.
+ coder->block_options.ignore_check = coder->ignore_check;
+
// Check the memory usage limit.
- memusage = lzma_raw_decoder_memusage(filters);
+ const uint64_t memusage = lzma_raw_decoder_memusage(filters);
+ lzma_ret ret;
+
if (memusage == UINT64_MAX) {
// One or more unknown Filter IDs.
ret = LZMA_OPTIONS_ERROR;
@@ -228,7 +235,7 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
// Free the allocated filter options since they are needed
// only to initialize the Block decoder.
- for (i = 0; i < LZMA_FILTERS_MAX; ++i)
+ for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
lzma_free(filters[i].options, allocator);
coder->block_options.filters = NULL;
@@ -264,8 +271,6 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
}
case SEQ_INDEX: {
- lzma_ret ret;
-
// If we don't have any input, don't call
// lzma_index_hash_decode() since it would return
// LZMA_BUF_ERROR, which we must not do here.
@@ -274,7 +279,7 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
// Decode the Index and compare it to the hash calculated
// from the sizes of the Blocks (if any).
- ret = lzma_index_hash_decode(coder->index_hash,
+ const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
in, in_pos, in_size);
if (ret != LZMA_STREAM_END)
return ret;
@@ -285,9 +290,6 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through
case SEQ_STREAM_FOOTER: {
- lzma_stream_flags footer_flags;
- lzma_ret ret;
-
// Copy the Stream Footer to the internal buffer.
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE);
@@ -301,7 +303,8 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
// Decode the Stream Footer. The decoder gives
// LZMA_FORMAT_ERROR if the magic bytes don't match,
// so convert that return code to LZMA_DATA_ERROR.
- ret = lzma_stream_footer_decode(
+ lzma_stream_flags footer_flags;
+ const lzma_ret ret = lzma_stream_footer_decode(
&footer_flags, coder->buffer);
if (ret != LZMA_OK)
return ret == LZMA_FORMAT_ERROR
@@ -374,8 +377,9 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
-stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+stream_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_stream_coder *coder = coder_ptr;
lzma_next_end(&coder->block_decoder, allocator);
lzma_index_hash_end(coder->index_hash, allocator);
lzma_free(coder, allocator);
@@ -384,16 +388,19 @@ stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_check
-stream_decoder_get_check(const lzma_coder *coder)
+stream_decoder_get_check(const void *coder_ptr)
{
+ const lzma_stream_coder *coder = coder_ptr;
return coder->stream_flags.check;
}
static lzma_ret
-stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+stream_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_stream_coder *coder = coder_ptr;
+
*memusage = coder->memusage;
*old_memlimit = coder->memlimit;
@@ -409,48 +416,49 @@ stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
extern lzma_ret
-lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_stream_decoder_init(
+ lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, uint32_t flags)
{
lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
- if (memlimit == 0)
- return LZMA_PROG_ERROR;
-
if (flags & ~LZMA_SUPPORTED_FLAGS)
return LZMA_OPTIONS_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_stream_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &stream_decode;
next->end = &stream_decoder_end;
next->get_check = &stream_decoder_get_check;
next->memconfig = &stream_decoder_memconfig;
- next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
- next->coder->index_hash = NULL;
+ coder->block_decoder = LZMA_NEXT_CODER_INIT;
+ coder->index_hash = NULL;
}
- next->coder->memlimit = memlimit;
- next->coder->memusage = LZMA_MEMUSAGE_BASE;
- next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
- next->coder->tell_unsupported_check
+ coder->memlimit = my_max(1, memlimit);
+ coder->memusage = LZMA_MEMUSAGE_BASE;
+ coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
+ coder->tell_unsupported_check
= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
- next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
- next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
- next->coder->first_stream = true;
+ coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
+ coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
+ coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
+ coder->first_stream = true;
- return stream_decoder_reset(next->coder, allocator);
+ return stream_decoder_reset(coder, allocator);
}
extern LZMA_API(lzma_ret)
lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{
- lzma_next_strm_init2(lzma_stream_decoder_init, strm, memlimit, flags);
+ lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
diff --git a/Utilities/cmliblzma/liblzma/common/stream_decoder.h b/Utilities/cmliblzma/liblzma/common/stream_decoder.h
index e54ac28f4..c13c6ba12 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_decoder.h
+++ b/Utilities/cmliblzma/liblzma/common/stream_decoder.h
@@ -15,7 +15,8 @@
#include "common.h"
-extern lzma_ret lzma_stream_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
+extern lzma_ret lzma_stream_decoder_init(
+ lzma_next_coder *next, const lzma_allocator *allocator,
+ uint64_t memlimit, uint32_t flags);
#endif
diff --git a/Utilities/cmliblzma/liblzma/common/stream_encoder.c b/Utilities/cmliblzma/liblzma/common/stream_encoder.c
index 1ba45acec..858cba473 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_encoder.c
@@ -10,12 +10,11 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_encoder.h"
#include "block_encoder.h"
#include "index_encoder.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_STREAM_HEADER,
SEQ_BLOCK_INIT,
@@ -26,7 +25,7 @@ struct lzma_coder_s {
} sequence;
/// True if Block encoder has been initialized by
- /// lzma_stream_encoder_init() or stream_encoder_update()
+ /// stream_encoder_init() or stream_encoder_update()
/// and thus doesn't need to be initialized in stream_encode().
bool block_encoder_is_initialized;
@@ -56,11 +55,11 @@ struct lzma_coder_s {
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
/// Block Header has biggest maximum size.
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
-};
+} lzma_stream_coder;
static lzma_ret
-block_encoder_init(lzma_coder *coder, lzma_allocator *allocator)
+block_encoder_init(lzma_stream_coder *coder, const lzma_allocator *allocator)
{
// Prepare the Block options. Even though Block encoder doesn't need
// compressed_size, uncompressed_size, and header_size to be
@@ -79,11 +78,13 @@ block_encoder_init(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-stream_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+stream_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_stream_coder *coder = coder_ptr;
+
// Main loop
while (*out_pos < out_size)
switch (coder->sequence) {
@@ -126,7 +127,7 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
}
// Initialize the Block encoder unless it was already
- // initialized by lzma_stream_encoder_init() or
+ // initialized by stream_encoder_init() or
// stream_encoder_update().
if (!coder->block_encoder_is_initialized)
return_if_error(block_encoder_init(coder, allocator));
@@ -147,13 +148,12 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
}
case SEQ_BLOCK_ENCODE: {
- lzma_vli unpadded_size;
-
- static const lzma_action convert[4] = {
+ static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
LZMA_RUN,
LZMA_SYNC_FLUSH,
LZMA_FINISH,
LZMA_FINISH,
+ LZMA_FINISH,
};
const lzma_ret ret = coder->block_encoder.code(
@@ -164,7 +164,7 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
return ret;
// Add a new Index Record.
- unpadded_size = lzma_block_unpadded_size(
+ const lzma_vli unpadded_size = lzma_block_unpadded_size(
&coder->block_options);
assert(unpadded_size != 0);
return_if_error(lzma_index_append(coder->index, allocator,
@@ -176,12 +176,6 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
}
case SEQ_INDEX_ENCODE: {
- const lzma_stream_flags stream_flags = {
- 0,
- lzma_index_size(coder->index),
- coder->block_options.check,
- };
-
// Call the Index encoder. It doesn't take any input, so
// those pointers can be NULL.
const lzma_ret ret = coder->index_encoder.code(
@@ -192,6 +186,11 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
return ret;
// Encode the Stream Footer into coder->buffer.
+ const lzma_stream_flags stream_flags = {
+ .version = 0,
+ .backward_size = lzma_index_size(coder->index),
+ .check = coder->block_options.check,
+ };
if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
!= LZMA_OK)
@@ -212,15 +211,15 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
static void
-stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
- size_t i;
+ lzma_stream_coder *coder = coder_ptr;
lzma_next_end(&coder->block_encoder, allocator);
lzma_next_end(&coder->index_encoder, allocator);
lzma_index_end(coder->index, allocator);
- for (i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
lzma_free(coder->filters[i].options, allocator);
lzma_free(coder, allocator);
@@ -229,22 +228,20 @@ stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-stream_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters,
const lzma_filter *reversed_filters)
{
- size_t i;
+ lzma_stream_coder *coder = coder_ptr;
if (coder->sequence <= SEQ_BLOCK_INIT) {
- lzma_ret ret;
-
// There is no incomplete Block waiting to be finished,
// thus we can change the whole filter chain. Start by
// trying to initialize the Block encoder with the new
// chain. This way we detect if the chain is valid.
coder->block_encoder_is_initialized = false;
coder->block_options.filters = (lzma_filter *)(filters);
- ret = block_encoder_init(coder, allocator);
+ const lzma_ret ret = block_encoder_init(coder, allocator);
coder->block_options.filters = coder->filters;
if (ret != LZMA_OK)
return ret;
@@ -264,62 +261,66 @@ stream_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
}
// Free the copy of the old chain and make a copy of the new chain.
- for (i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
lzma_free(coder->filters[i].options, allocator);
return lzma_filters_copy(filters, coder->filters, allocator);
}
-extern lzma_ret
-lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+static lzma_ret
+stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *filters, lzma_check check)
{
- lzma_stream_flags stream_flags = { 0, 0, check };
-
- lzma_next_coder_init(&lzma_stream_encoder_init, next, allocator);
+ lzma_next_coder_init(&stream_encoder_init, next, allocator);
if (filters == NULL)
return LZMA_PROG_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_stream_coder *coder = next->coder;
+
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &stream_encode;
next->end = &stream_encoder_end;
next->update = &stream_encoder_update;
- next->coder->filters[0].id = LZMA_VLI_UNKNOWN;
- next->coder->block_encoder = LZMA_NEXT_CODER_INIT;
- next->coder->index_encoder = LZMA_NEXT_CODER_INIT;
- next->coder->index = NULL;
+ coder->filters[0].id = LZMA_VLI_UNKNOWN;
+ coder->block_encoder = LZMA_NEXT_CODER_INIT;
+ coder->index_encoder = LZMA_NEXT_CODER_INIT;
+ coder->index = NULL;
}
// Basic initializations
- next->coder->sequence = SEQ_STREAM_HEADER;
- next->coder->block_options.version = 0;
- next->coder->block_options.check = check;
+ coder->sequence = SEQ_STREAM_HEADER;
+ coder->block_options.version = 0;
+ coder->block_options.check = check;
// Initialize the Index
- lzma_index_end(next->coder->index, allocator);
- next->coder->index = lzma_index_init(allocator);
- if (next->coder->index == NULL)
+ lzma_index_end(coder->index, allocator);
+ coder->index = lzma_index_init(allocator);
+ if (coder->index == NULL)
return LZMA_MEM_ERROR;
// Encode the Stream Header
+ lzma_stream_flags stream_flags = {
+ .version = 0,
+ .check = check,
+ };
return_if_error(lzma_stream_header_encode(
- &stream_flags, next->coder->buffer));
+ &stream_flags, coder->buffer));
- next->coder->buffer_pos = 0;
- next->coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
+ coder->buffer_pos = 0;
+ coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
// Initialize the Block encoder. This way we detect unsupported
// filter chains when initializing the Stream encoder instead of
// giving an error after Stream Header has already written out.
- return stream_encoder_update(
- next->coder, allocator, filters, NULL);
+ return stream_encoder_update(coder, allocator, filters, NULL);
}
@@ -327,11 +328,12 @@ extern LZMA_API(lzma_ret)
lzma_stream_encoder(lzma_stream *strm,
const lzma_filter *filters, lzma_check check)
{
- lzma_next_strm_init2(lzma_stream_encoder_init, strm, filters, check);
+ lzma_next_strm_init(stream_encoder_init, strm, filters, check);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;
diff --git a/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c b/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c
new file mode 100644
index 000000000..2efe44c25
--- /dev/null
+++ b/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c
@@ -0,0 +1,1143 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file stream_encoder_mt.c
+/// \brief Multithreaded .xz Stream encoder
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+#include "easy_preset.h"
+#include "block_encoder.h"
+#include "block_buffer_encoder.h"
+#include "index_encoder.h"
+#include "outqueue.h"
+
+
+/// Maximum supported block size. This makes it simpler to prevent integer
+/// overflows if we are given unusually large block size.
+#define BLOCK_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX)
+
+
+typedef enum {
+ /// Waiting for work.
+ THR_IDLE,
+
+ /// Encoding is in progress.
+ THR_RUN,
+
+ /// Encoding is in progress but no more input data will
+ /// be read.
+ THR_FINISH,
+
+ /// The main thread wants the thread to stop whatever it was doing
+ /// but not exit.
+ THR_STOP,
+
+ /// The main thread wants the thread to exit. We could use
+ /// cancellation but since there's stopped anyway, this is lazier.
+ THR_EXIT,
+
+} worker_state;
+
+typedef struct lzma_stream_coder_s lzma_stream_coder;
+
+typedef struct worker_thread_s worker_thread;
+struct worker_thread_s {
+ worker_state state;
+
+ /// Input buffer of coder->block_size bytes. The main thread will
+ /// put new input into this and update in_size accordingly. Once
+ /// no more input is coming, state will be set to THR_FINISH.
+ uint8_t *in;
+
+ /// Amount of data available in the input buffer. This is modified
+ /// only by the main thread.
+ size_t in_size;
+
+ /// Output buffer for this thread. This is set by the main
+ /// thread every time a new Block is started with this thread
+ /// structure.
+ lzma_outbuf *outbuf;
+
+ /// Pointer to the main structure is needed when putting this
+ /// thread back to the stack of free threads.
+ lzma_stream_coder *coder;
+
+ /// The allocator is set by the main thread. Since a copy of the
+ /// pointer is kept here, the application must not change the
+ /// allocator before calling lzma_end().
+ const lzma_allocator *allocator;
+
+ /// Amount of uncompressed data that has already been compressed.
+ uint64_t progress_in;
+
+ /// Amount of compressed data that is ready.
+ uint64_t progress_out;
+
+ /// Block encoder
+ lzma_next_coder block_encoder;
+
+ /// Compression options for this Block
+ lzma_block block_options;
+
+ /// Next structure in the stack of free worker threads.
+ worker_thread *next;
+
+ mythread_mutex mutex;
+ mythread_cond cond;
+
+ /// The ID of this thread is used to join the thread
+ /// when it's not needed anymore.
+ mythread thread_id;
+};
+
+
+struct lzma_stream_coder_s {
+ enum {
+ SEQ_STREAM_HEADER,
+ SEQ_BLOCK,
+ SEQ_INDEX,
+ SEQ_STREAM_FOOTER,
+ } sequence;
+
+ /// Start a new Block every block_size bytes of input unless
+ /// LZMA_FULL_FLUSH or LZMA_FULL_BARRIER is used earlier.
+ size_t block_size;
+
+ /// The filter chain currently in use
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+
+ /// Index to hold sizes of the Blocks
+ lzma_index *index;
+
+ /// Index encoder
+ lzma_next_coder index_encoder;
+
+
+ /// Stream Flags for encoding the Stream Header and Stream Footer.
+ lzma_stream_flags stream_flags;
+
+ /// Buffer to hold Stream Header and Stream Footer.
+ uint8_t header[LZMA_STREAM_HEADER_SIZE];
+
+ /// Read position in header[]
+ size_t header_pos;
+
+
+ /// Output buffer queue for compressed data
+ lzma_outq outq;
+
+
+ /// Maximum wait time if cannot use all the input and cannot
+ /// fill the output buffer. This is in milliseconds.
+ uint32_t timeout;
+
+
+ /// Error code from a worker thread
+ lzma_ret thread_error;
+
+ /// Array of allocated thread-specific structures
+ worker_thread *threads;
+
+ /// Number of structures in "threads" above. This is also the
+ /// number of threads that will be created at maximum.
+ uint32_t threads_max;
+
+ /// Number of thread structures that have been initialized, and
+ /// thus the number of worker threads actually created so far.
+ uint32_t threads_initialized;
+
+ /// Stack of free threads. When a thread finishes, it puts itself
+ /// back into this stack. This starts as empty because threads
+ /// are created only when actually needed.
+ worker_thread *threads_free;
+
+ /// The most recent worker thread to which the main thread writes
+ /// the new input from the application.
+ worker_thread *thr;
+
+
+ /// Amount of uncompressed data in Blocks that have already
+ /// been finished.
+ uint64_t progress_in;
+
+ /// Amount of compressed data in Stream Header + Blocks that
+ /// have already been finished.
+ uint64_t progress_out;
+
+
+ mythread_mutex mutex;
+ mythread_cond cond;
+};
+
+
+/// Tell the main thread that something has gone wrong.
+static void
+worker_error(worker_thread *thr, lzma_ret ret)
+{
+ assert(ret != LZMA_OK);
+ assert(ret != LZMA_STREAM_END);
+
+ mythread_sync(thr->coder->mutex) {
+ if (thr->coder->thread_error == LZMA_OK)
+ thr->coder->thread_error = ret;
+
+ mythread_cond_signal(&thr->coder->cond);
+ }
+
+ return;
+}
+
+
+static worker_state
+worker_encode(worker_thread *thr, worker_state state)
+{
+ assert(thr->progress_in == 0);
+ assert(thr->progress_out == 0);
+
+ // Set the Block options.
+ thr->block_options = (lzma_block){
+ .version = 0,
+ .check = thr->coder->stream_flags.check,
+ .compressed_size = thr->coder->outq.buf_size_max,
+ .uncompressed_size = thr->coder->block_size,
+
+ // TODO: To allow changing the filter chain, the filters
+ // array must be copied to each worker_thread.
+ .filters = thr->coder->filters,
+ };
+
+ // Calculate maximum size of the Block Header. This amount is
+ // reserved in the beginning of the buffer so that Block Header
+ // along with Compressed Size and Uncompressed Size can be
+ // written there.
+ lzma_ret ret = lzma_block_header_size(&thr->block_options);
+ if (ret != LZMA_OK) {
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ // Initialize the Block encoder.
+ ret = lzma_block_encoder_init(&thr->block_encoder,
+ thr->allocator, &thr->block_options);
+ if (ret != LZMA_OK) {
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ size_t in_pos = 0;
+ size_t in_size = 0;
+
+ thr->outbuf->size = thr->block_options.header_size;
+ const size_t out_size = thr->coder->outq.buf_size_max;
+
+ do {
+ mythread_sync(thr->mutex) {
+ // Store in_pos and out_pos into *thr so that
+ // an application may read them via
+ // lzma_get_progress() to get progress information.
+ //
+ // NOTE: These aren't updated when the encoding
+ // finishes. Instead, the final values are taken
+ // later from thr->outbuf.
+ thr->progress_in = in_pos;
+ thr->progress_out = thr->outbuf->size;
+
+ while (in_size == thr->in_size
+ && thr->state == THR_RUN)
+ mythread_cond_wait(&thr->cond, &thr->mutex);
+
+ state = thr->state;
+ in_size = thr->in_size;
+ }
+
+ // Return if we were asked to stop or exit.
+ if (state >= THR_STOP)
+ return state;
+
+ lzma_action action = state == THR_FINISH
+ ? LZMA_FINISH : LZMA_RUN;
+
+ // Limit the amount of input given to the Block encoder
+ // at once. This way this thread can react fairly quickly
+ // if the main thread wants us to stop or exit.
+ static const size_t in_chunk_max = 16384;
+ size_t in_limit = in_size;
+ if (in_size - in_pos > in_chunk_max) {
+ in_limit = in_pos + in_chunk_max;
+ action = LZMA_RUN;
+ }
+
+ ret = thr->block_encoder.code(
+ thr->block_encoder.coder, thr->allocator,
+ thr->in, &in_pos, in_limit, thr->outbuf->buf,
+ &thr->outbuf->size, out_size, action);
+ } while (ret == LZMA_OK && thr->outbuf->size < out_size);
+
+ switch (ret) {
+ case LZMA_STREAM_END:
+ assert(state == THR_FINISH);
+
+ // Encode the Block Header. By doing it after
+ // the compression, we can store the Compressed Size
+ // and Uncompressed Size fields.
+ ret = lzma_block_header_encode(&thr->block_options,
+ thr->outbuf->buf);
+ if (ret != LZMA_OK) {
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ break;
+
+ case LZMA_OK:
+ // The data was incompressible. Encode it using uncompressed
+ // LZMA2 chunks.
+ //
+ // First wait that we have gotten all the input.
+ mythread_sync(thr->mutex) {
+ while (thr->state == THR_RUN)
+ mythread_cond_wait(&thr->cond, &thr->mutex);
+
+ state = thr->state;
+ in_size = thr->in_size;
+ }
+
+ if (state >= THR_STOP)
+ return state;
+
+ // Do the encoding. This takes care of the Block Header too.
+ thr->outbuf->size = 0;
+ ret = lzma_block_uncomp_encode(&thr->block_options,
+ thr->in, in_size, thr->outbuf->buf,
+ &thr->outbuf->size, out_size);
+
+ // It shouldn't fail.
+ if (ret != LZMA_OK) {
+ worker_error(thr, LZMA_PROG_ERROR);
+ return THR_STOP;
+ }
+
+ break;
+
+ default:
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ // Set the size information that will be read by the main thread
+ // to write the Index field.
+ thr->outbuf->unpadded_size
+ = lzma_block_unpadded_size(&thr->block_options);
+ assert(thr->outbuf->unpadded_size != 0);
+ thr->outbuf->uncompressed_size = thr->block_options.uncompressed_size;
+
+ return THR_FINISH;
+}
+
+
+static MYTHREAD_RET_TYPE
+worker_start(void *thr_ptr)
+{
+ worker_thread *thr = thr_ptr;
+ worker_state state = THR_IDLE; // Init to silence a warning
+
+ while (true) {
+ // Wait for work.
+ mythread_sync(thr->mutex) {
+ while (true) {
+ // The thread is already idle so if we are
+ // requested to stop, just set the state.
+ if (thr->state == THR_STOP) {
+ thr->state = THR_IDLE;
+ mythread_cond_signal(&thr->cond);
+ }
+
+ state = thr->state;
+ if (state != THR_IDLE)
+ break;
+
+ mythread_cond_wait(&thr->cond, &thr->mutex);
+ }
+ }
+
+ assert(state != THR_IDLE);
+ assert(state != THR_STOP);
+
+ if (state <= THR_FINISH)
+ state = worker_encode(thr, state);
+
+ if (state == THR_EXIT)
+ break;
+
+ // Mark the thread as idle unless the main thread has
+ // told us to exit. Signal is needed for the case
+ // where the main thread is waiting for the threads to stop.
+ mythread_sync(thr->mutex) {
+ if (thr->state != THR_EXIT) {
+ thr->state = THR_IDLE;
+ mythread_cond_signal(&thr->cond);
+ }
+ }
+
+ mythread_sync(thr->coder->mutex) {
+ // Mark the output buffer as finished if
+ // no errors occurred.
+ thr->outbuf->finished = state == THR_FINISH;
+
+ // Update the main progress info.
+ thr->coder->progress_in
+ += thr->outbuf->uncompressed_size;
+ thr->coder->progress_out += thr->outbuf->size;
+ thr->progress_in = 0;
+ thr->progress_out = 0;
+
+ // Return this thread to the stack of free threads.
+ thr->next = thr->coder->threads_free;
+ thr->coder->threads_free = thr;
+
+ mythread_cond_signal(&thr->coder->cond);
+ }
+ }
+
+ // Exiting, free the resources.
+ mythread_mutex_destroy(&thr->mutex);
+ mythread_cond_destroy(&thr->cond);
+
+ lzma_next_end(&thr->block_encoder, thr->allocator);
+ lzma_free(thr->in, thr->allocator);
+ return MYTHREAD_RET_VALUE;
+}
+
+
+/// Make the threads stop but not exit. Optionally wait for them to stop.
+static void
+threads_stop(lzma_stream_coder *coder, bool wait_for_threads)
+{
+ // Tell the threads to stop.
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ coder->threads[i].state = THR_STOP;
+ mythread_cond_signal(&coder->threads[i].cond);
+ }
+ }
+
+ if (!wait_for_threads)
+ return;
+
+ // Wait for the threads to settle in the idle state.
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ while (coder->threads[i].state != THR_IDLE)
+ mythread_cond_wait(&coder->threads[i].cond,
+ &coder->threads[i].mutex);
+ }
+ }
+
+ return;
+}
+
+
+/// Stop the threads and free the resources associated with them.
+/// Wait until the threads have exited.
+static void
+threads_end(lzma_stream_coder *coder, const lzma_allocator *allocator)
+{
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ coder->threads[i].state = THR_EXIT;
+ mythread_cond_signal(&coder->threads[i].cond);
+ }
+ }
+
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ int ret = mythread_join(coder->threads[i].thread_id);
+ assert(ret == 0);
+ (void)ret;
+ }
+
+ lzma_free(coder->threads, allocator);
+ return;
+}
+
+
+/// Initialize a new worker_thread structure and create a new thread.
+static lzma_ret
+initialize_new_thread(lzma_stream_coder *coder,
+ const lzma_allocator *allocator)
+{
+ worker_thread *thr = &coder->threads[coder->threads_initialized];
+
+ thr->in = lzma_alloc(coder->block_size, allocator);
+ if (thr->in == NULL)
+ return LZMA_MEM_ERROR;
+
+ if (mythread_mutex_init(&thr->mutex))
+ goto error_mutex;
+
+ if (mythread_cond_init(&thr->cond))
+ goto error_cond;
+
+ thr->state = THR_IDLE;
+ thr->allocator = allocator;
+ thr->coder = coder;
+ thr->progress_in = 0;
+ thr->progress_out = 0;
+ thr->block_encoder = LZMA_NEXT_CODER_INIT;
+
+ if (mythread_create(&thr->thread_id, &worker_start, thr))
+ goto error_thread;
+
+ ++coder->threads_initialized;
+ coder->thr = thr;
+
+ return LZMA_OK;
+
+error_thread:
+ mythread_cond_destroy(&thr->cond);
+
+error_cond:
+ mythread_mutex_destroy(&thr->mutex);
+
+error_mutex:
+ lzma_free(thr->in, allocator);
+ return LZMA_MEM_ERROR;
+}
+
+
+static lzma_ret
+get_thread(lzma_stream_coder *coder, const lzma_allocator *allocator)
+{
+ // If there are no free output subqueues, there is no
+ // point to try getting a thread.
+ if (!lzma_outq_has_buf(&coder->outq))
+ return LZMA_OK;
+
+ // If there is a free structure on the stack, use it.
+ mythread_sync(coder->mutex) {
+ if (coder->threads_free != NULL) {
+ coder->thr = coder->threads_free;
+ coder->threads_free = coder->threads_free->next;
+ }
+ }
+
+ if (coder->thr == NULL) {
+ // If there are no uninitialized structures left, return.
+ if (coder->threads_initialized == coder->threads_max)
+ return LZMA_OK;
+
+ // Initialize a new thread.
+ return_if_error(initialize_new_thread(coder, allocator));
+ }
+
+ // Reset the parts of the thread state that have to be done
+ // in the main thread.
+ mythread_sync(coder->thr->mutex) {
+ coder->thr->state = THR_RUN;
+ coder->thr->in_size = 0;
+ coder->thr->outbuf = lzma_outq_get_buf(&coder->outq);
+ mythread_cond_signal(&coder->thr->cond);
+ }
+
+ return LZMA_OK;
+}
+
+
+static lzma_ret
+stream_encode_in(lzma_stream_coder *coder, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, lzma_action action)
+{
+ while (*in_pos < in_size
+ || (coder->thr != NULL && action != LZMA_RUN)) {
+ if (coder->thr == NULL) {
+ // Get a new thread.
+ const lzma_ret ret = get_thread(coder, allocator);
+ if (coder->thr == NULL)
+ return ret;
+ }
+
+ // Copy the input data to thread's buffer.
+ size_t thr_in_size = coder->thr->in_size;
+ lzma_bufcpy(in, in_pos, in_size, coder->thr->in,
+ &thr_in_size, coder->block_size);
+
+ // Tell the Block encoder to finish if
+ // - it has got block_size bytes of input; or
+ // - all input was used and LZMA_FINISH, LZMA_FULL_FLUSH,
+ // or LZMA_FULL_BARRIER was used.
+ //
+ // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER.
+ const bool finish = thr_in_size == coder->block_size
+ || (*in_pos == in_size && action != LZMA_RUN);
+
+ bool block_error = false;
+
+ mythread_sync(coder->thr->mutex) {
+ if (coder->thr->state == THR_IDLE) {
+ // Something has gone wrong with the Block
+ // encoder. It has set coder->thread_error
+ // which we will read a few lines later.
+ block_error = true;
+ } else {
+ // Tell the Block encoder its new amount
+ // of input and update the state if needed.
+ coder->thr->in_size = thr_in_size;
+
+ if (finish)
+ coder->thr->state = THR_FINISH;
+
+ mythread_cond_signal(&coder->thr->cond);
+ }
+ }
+
+ if (block_error) {
+ lzma_ret ret;
+
+ mythread_sync(coder->mutex) {
+ ret = coder->thread_error;
+ }
+
+ return ret;
+ }
+
+ if (finish)
+ coder->thr = NULL;
+ }
+
+ return LZMA_OK;
+}
+
+
+/// Wait until more input can be consumed, more output can be read, or
+/// an optional timeout is reached.
+static bool
+wait_for_work(lzma_stream_coder *coder, mythread_condtime *wait_abs,
+ bool *has_blocked, bool has_input)
+{
+ if (coder->timeout != 0 && !*has_blocked) {
+ // Every time when stream_encode_mt() is called via
+ // lzma_code(), *has_blocked starts as false. We set it
+ // to true here and calculate the absolute time when
+ // we must return if there's nothing to do.
+ //
+ // The idea of *has_blocked is to avoid unneeded calls
+ // to mythread_condtime_set(), which may do a syscall
+ // depending on the operating system.
+ *has_blocked = true;
+ mythread_condtime_set(wait_abs, &coder->cond, coder->timeout);
+ }
+
+ bool timed_out = false;
+
+ mythread_sync(coder->mutex) {
+ // There are four things that we wait. If one of them
+ // becomes possible, we return.
+ // - If there is input left, we need to get a free
+ // worker thread and an output buffer for it.
+ // - Data ready to be read from the output queue.
+ // - A worker thread indicates an error.
+ // - Time out occurs.
+ while ((!has_input || coder->threads_free == NULL
+ || !lzma_outq_has_buf(&coder->outq))
+ && !lzma_outq_is_readable(&coder->outq)
+ && coder->thread_error == LZMA_OK
+ && !timed_out) {
+ if (coder->timeout != 0)
+ timed_out = mythread_cond_timedwait(
+ &coder->cond, &coder->mutex,
+ wait_abs) != 0;
+ else
+ mythread_cond_wait(&coder->cond,
+ &coder->mutex);
+ }
+ }
+
+ return timed_out;
+}
+
+
+static lzma_ret
+stream_encode_mt(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+ lzma_stream_coder *coder = coder_ptr;
+
+ switch (coder->sequence) {
+ case SEQ_STREAM_HEADER:
+ lzma_bufcpy(coder->header, &coder->header_pos,
+ sizeof(coder->header),
+ out, out_pos, out_size);
+ if (coder->header_pos < sizeof(coder->header))
+ return LZMA_OK;
+
+ coder->header_pos = 0;
+ coder->sequence = SEQ_BLOCK;
+
+ // Fall through
+
+ case SEQ_BLOCK: {
+ // Initialized to silence warnings.
+ lzma_vli unpadded_size = 0;
+ lzma_vli uncompressed_size = 0;
+ lzma_ret ret = LZMA_OK;
+
+ // These are for wait_for_work().
+ bool has_blocked = false;
+ mythread_condtime wait_abs;
+
+ while (true) {
+ mythread_sync(coder->mutex) {
+ // Check for Block encoder errors.
+ ret = coder->thread_error;
+ if (ret != LZMA_OK) {
+ assert(ret != LZMA_STREAM_END);
+ break;
+ }
+
+ // Try to read compressed data to out[].
+ ret = lzma_outq_read(&coder->outq,
+ out, out_pos, out_size,
+ &unpadded_size,
+ &uncompressed_size);
+ }
+
+ if (ret == LZMA_STREAM_END) {
+ // End of Block. Add it to the Index.
+ ret = lzma_index_append(coder->index,
+ allocator, unpadded_size,
+ uncompressed_size);
+
+ // If we didn't fill the output buffer yet,
+ // try to read more data. Maybe the next
+ // outbuf has been finished already too.
+ if (*out_pos < out_size)
+ continue;
+ }
+
+ if (ret != LZMA_OK) {
+ // coder->thread_error was set or
+ // lzma_index_append() failed.
+ threads_stop(coder, false);
+ return ret;
+ }
+
+ // Try to give uncompressed data to a worker thread.
+ ret = stream_encode_in(coder, allocator,
+ in, in_pos, in_size, action);
+ if (ret != LZMA_OK) {
+ threads_stop(coder, false);
+ return ret;
+ }
+
+ // See if we should wait or return.
+ //
+ // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER.
+ if (*in_pos == in_size) {
+ // LZMA_RUN: More data is probably coming
+ // so return to let the caller fill the
+ // input buffer.
+ if (action == LZMA_RUN)
+ return LZMA_OK;
+
+ // LZMA_FULL_BARRIER: The same as with
+ // LZMA_RUN but tell the caller that the
+ // barrier was completed.
+ if (action == LZMA_FULL_BARRIER)
+ return LZMA_STREAM_END;
+
+ // Finishing or flushing isn't completed until
+ // all input data has been encoded and copied
+ // to the output buffer.
+ if (lzma_outq_is_empty(&coder->outq)) {
+ // LZMA_FINISH: Continue to encode
+ // the Index field.
+ if (action == LZMA_FINISH)
+ break;
+
+ // LZMA_FULL_FLUSH: Return to tell
+ // the caller that flushing was
+ // completed.
+ if (action == LZMA_FULL_FLUSH)
+ return LZMA_STREAM_END;
+ }
+ }
+
+ // Return if there is no output space left.
+ // This check must be done after testing the input
+ // buffer, because we might want to use a different
+ // return code.
+ if (*out_pos == out_size)
+ return LZMA_OK;
+
+ // Neither in nor out has been used completely.
+ // Wait until there's something we can do.
+ if (wait_for_work(coder, &wait_abs, &has_blocked,
+ *in_pos < in_size))
+ return LZMA_TIMED_OUT;
+ }
+
+ // All Blocks have been encoded and the threads have stopped.
+ // Prepare to encode the Index field.
+ return_if_error(lzma_index_encoder_init(
+ &coder->index_encoder, allocator,
+ coder->index));
+ coder->sequence = SEQ_INDEX;
+
+ // Update the progress info to take the Index and
+ // Stream Footer into account. Those are very fast to encode
+ // so in terms of progress information they can be thought
+ // to be ready to be copied out.
+ coder->progress_out += lzma_index_size(coder->index)
+ + LZMA_STREAM_HEADER_SIZE;
+ }
+
+ // Fall through
+
+ case SEQ_INDEX: {
+ // Call the Index encoder. It doesn't take any input, so
+ // those pointers can be NULL.
+ const lzma_ret ret = coder->index_encoder.code(
+ coder->index_encoder.coder, allocator,
+ NULL, NULL, 0,
+ out, out_pos, out_size, LZMA_RUN);
+ if (ret != LZMA_STREAM_END)
+ return ret;
+
+ // Encode the Stream Footer into coder->buffer.
+ coder->stream_flags.backward_size
+ = lzma_index_size(coder->index);
+ if (lzma_stream_footer_encode(&coder->stream_flags,
+ coder->header) != LZMA_OK)
+ return LZMA_PROG_ERROR;
+
+ coder->sequence = SEQ_STREAM_FOOTER;
+ }
+
+ // Fall through
+
+ case SEQ_STREAM_FOOTER:
+ lzma_bufcpy(coder->header, &coder->header_pos,
+ sizeof(coder->header),
+ out, out_pos, out_size);
+ return coder->header_pos < sizeof(coder->header)
+ ? LZMA_OK : LZMA_STREAM_END;
+ }
+
+ assert(0);
+ return LZMA_PROG_ERROR;
+}
+
+
+static void
+stream_encoder_mt_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+ lzma_stream_coder *coder = coder_ptr;
+
+ // Threads must be killed before the output queue can be freed.
+ threads_end(coder, allocator);
+ lzma_outq_end(&coder->outq, allocator);
+
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ lzma_free(coder->filters[i].options, allocator);
+
+ lzma_next_end(&coder->index_encoder, allocator);
+ lzma_index_end(coder->index, allocator);
+
+ mythread_cond_destroy(&coder->cond);
+ mythread_mutex_destroy(&coder->mutex);
+
+ lzma_free(coder, allocator);
+ return;
+}
+
+
+/// Options handling for lzma_stream_encoder_mt_init() and
+/// lzma_stream_encoder_mt_memusage()
+static lzma_ret
+get_options(const lzma_mt *options, lzma_options_easy *opt_easy,
+ const lzma_filter **filters, uint64_t *block_size,
+ uint64_t *outbuf_size_max)
+{
+ // Validate some of the options.
+ if (options == NULL)
+ return LZMA_PROG_ERROR;
+
+ if (options->flags != 0 || options->threads == 0
+ || options->threads > LZMA_THREADS_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ if (options->filters != NULL) {
+ // Filter chain was given, use it as is.
+ *filters = options->filters;
+ } else {
+ // Use a preset.
+ if (lzma_easy_preset(opt_easy, options->preset))
+ return LZMA_OPTIONS_ERROR;
+
+ *filters = opt_easy->filters;
+ }
+
+ // Block size
+ if (options->block_size > 0) {
+ if (options->block_size > BLOCK_SIZE_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ *block_size = options->block_size;
+ } else {
+ // Determine the Block size from the filter chain.
+ *block_size = lzma_mt_block_size(*filters);
+ if (*block_size == 0)
+ return LZMA_OPTIONS_ERROR;
+
+ assert(*block_size <= BLOCK_SIZE_MAX);
+ }
+
+ // Calculate the maximum amount output that a single output buffer
+ // may need to hold. This is the same as the maximum total size of
+ // a Block.
+ *outbuf_size_max = lzma_block_buffer_bound64(*block_size);
+ if (*outbuf_size_max == 0)
+ return LZMA_MEM_ERROR;
+
+ return LZMA_OK;
+}
+
+
+static void
+get_progress(void *coder_ptr, uint64_t *progress_in, uint64_t *progress_out)
+{
+ lzma_stream_coder *coder = coder_ptr;
+
+ // Lock coder->mutex to prevent finishing threads from moving their
+ // progress info from the worker_thread structure to lzma_stream_coder.
+ mythread_sync(coder->mutex) {
+ *progress_in = coder->progress_in;
+ *progress_out = coder->progress_out;
+
+ for (size_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ *progress_in += coder->threads[i].progress_in;
+ *progress_out += coder->threads[i]
+ .progress_out;
+ }
+ }
+ }
+
+ return;
+}
+
+
+static lzma_ret
+stream_encoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator,
+ const lzma_mt *options)
+{
+ lzma_next_coder_init(&stream_encoder_mt_init, next, allocator);
+
+ // Get the filter chain.
+ lzma_options_easy easy;
+ const lzma_filter *filters;
+ uint64_t block_size;
+ uint64_t outbuf_size_max;
+ return_if_error(get_options(options, &easy, &filters,
+ &block_size, &outbuf_size_max));
+
+#if SIZE_MAX < UINT64_MAX
+ if (block_size > SIZE_MAX)
+ return LZMA_MEM_ERROR;
+#endif
+
+ // Validate the filter chain so that we can give an error in this
+ // function instead of delaying it to the first call to lzma_code().
+ // The memory usage calculation verifies the filter chain as
+ // a side effect so we take advatange of that.
+ if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ // Validate the Check ID.
+ if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
+ return LZMA_PROG_ERROR;
+
+ if (!lzma_check_is_supported(options->check))
+ return LZMA_UNSUPPORTED_CHECK;
+
+ // Allocate and initialize the base structure if needed.
+ lzma_stream_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
+ if (coder == NULL)
+ return LZMA_MEM_ERROR;
+
+ next->coder = coder;
+
+ // For the mutex and condition variable initializations
+ // the error handling has to be done here because
+ // stream_encoder_mt_end() doesn't know if they have
+ // already been initialized or not.
+ if (mythread_mutex_init(&coder->mutex)) {
+ lzma_free(coder, allocator);
+ next->coder = NULL;
+ return LZMA_MEM_ERROR;
+ }
+
+ if (mythread_cond_init(&coder->cond)) {
+ mythread_mutex_destroy(&coder->mutex);
+ lzma_free(coder, allocator);
+ next->coder = NULL;
+ return LZMA_MEM_ERROR;
+ }
+
+ next->code = &stream_encode_mt;
+ next->end = &stream_encoder_mt_end;
+ next->get_progress = &get_progress;
+// next->update = &stream_encoder_mt_update;
+
+ coder->filters[0].id = LZMA_VLI_UNKNOWN;
+ coder->index_encoder = LZMA_NEXT_CODER_INIT;
+ coder->index = NULL;
+ memzero(&coder->outq, sizeof(coder->outq));
+ coder->threads = NULL;
+ coder->threads_max = 0;
+ coder->threads_initialized = 0;
+ }
+
+ // Basic initializations
+ coder->sequence = SEQ_STREAM_HEADER;
+ coder->block_size = (size_t)(block_size);
+ coder->thread_error = LZMA_OK;
+ coder->thr = NULL;
+
+ // Allocate the thread-specific base structures.
+ assert(options->threads > 0);
+ if (coder->threads_max != options->threads) {
+ threads_end(coder, allocator);
+
+ coder->threads = NULL;
+ coder->threads_max = 0;
+
+ coder->threads_initialized = 0;
+ coder->threads_free = NULL;
+
+ coder->threads = lzma_alloc(
+ options->threads * sizeof(worker_thread),
+ allocator);
+ if (coder->threads == NULL)
+ return LZMA_MEM_ERROR;
+
+ coder->threads_max = options->threads;
+ } else {
+ // Reuse the old structures and threads. Tell the running
+ // threads to stop and wait until they have stopped.
+ threads_stop(coder, true);
+ }
+
+ // Output queue
+ return_if_error(lzma_outq_init(&coder->outq, allocator,
+ outbuf_size_max, options->threads));
+
+ // Timeout
+ coder->timeout = options->timeout;
+
+ // Free the old filter chain and copy the new one.
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ lzma_free(coder->filters[i].options, allocator);
+
+ return_if_error(lzma_filters_copy(
+ filters, coder->filters, allocator));
+
+ // Index
+ lzma_index_end(coder->index, allocator);
+ coder->index = lzma_index_init(allocator);
+ if (coder->index == NULL)
+ return LZMA_MEM_ERROR;
+
+ // Stream Header
+ coder->stream_flags.version = 0;
+ coder->stream_flags.check = options->check;
+ return_if_error(lzma_stream_header_encode(
+ &coder->stream_flags, coder->header));
+
+ coder->header_pos = 0;
+
+ // Progress info
+ coder->progress_in = 0;
+ coder->progress_out = LZMA_STREAM_HEADER_SIZE;
+
+ return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_encoder_mt(lzma_stream *strm, const lzma_mt *options)
+{
+ lzma_next_strm_init(stream_encoder_mt_init, strm, options);
+
+ strm->internal->supported_actions[LZMA_RUN] = true;
+// strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
+ strm->internal->supported_actions[LZMA_FINISH] = true;
+
+ return LZMA_OK;
+}
+
+
+// This function name is a monster but it's consistent with the older
+// monster names. :-( 31 chars is the max that C99 requires so in that
+// sense it's not too long. ;-)
+extern LZMA_API(uint64_t)
+lzma_stream_encoder_mt_memusage(const lzma_mt *options)
+{
+ lzma_options_easy easy;
+ const lzma_filter *filters;
+ uint64_t block_size;
+ uint64_t outbuf_size_max;
+
+ if (get_options(options, &easy, &filters, &block_size,
+ &outbuf_size_max) != LZMA_OK)
+ return UINT64_MAX;
+
+ // Memory usage of the input buffers
+ const uint64_t inbuf_memusage = options->threads * block_size;
+
+ // Memory usage of the filter encoders
+ uint64_t filters_memusage = lzma_raw_encoder_memusage(filters);
+ if (filters_memusage == UINT64_MAX)
+ return UINT64_MAX;
+
+ filters_memusage *= options->threads;
+
+ // Memory usage of the output queue
+ const uint64_t outq_memusage = lzma_outq_memusage(
+ outbuf_size_max, options->threads);
+ if (outq_memusage == UINT64_MAX)
+ return UINT64_MAX;
+
+ // Sum them with overflow checking.
+ uint64_t total_memusage = LZMA_MEMUSAGE_BASE
+ + sizeof(lzma_stream_coder)
+ + options->threads * sizeof(worker_thread);
+
+ if (UINT64_MAX - total_memusage < inbuf_memusage)
+ return UINT64_MAX;
+
+ total_memusage += inbuf_memusage;
+
+ if (UINT64_MAX - total_memusage < filters_memusage)
+ return UINT64_MAX;
+
+ total_memusage += filters_memusage;
+
+ if (UINT64_MAX - total_memusage < outq_memusage)
+ return UINT64_MAX;
+
+ return total_memusage + outq_memusage;
+}
diff --git a/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c b/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c
index 8cf48a4ca..1bc2f97c5 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c
@@ -30,15 +30,13 @@ stream_flags_decode(lzma_stream_flags *options, const uint8_t *in)
extern LZMA_API(lzma_ret)
lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
{
- uint32_t crc;
-
// Magic
if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
return LZMA_FORMAT_ERROR;
// Verify the CRC32 so we can distinguish between corrupt
// and unsupported files.
- crc = lzma_crc32(in + sizeof(lzma_header_magic),
+ const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
LZMA_STREAM_FLAGS_SIZE, 0);
if (crc != unaligned_read32le(in + sizeof(lzma_header_magic)
+ LZMA_STREAM_FLAGS_SIZE))
@@ -61,15 +59,13 @@ lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
extern LZMA_API(lzma_ret)
lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
{
- uint32_t crc;
-
// Magic
if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
return LZMA_FORMAT_ERROR;
// CRC32
- crc = lzma_crc32(in + sizeof(uint32_t),
+ const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
if (crc != unaligned_read32le(in))
return LZMA_DATA_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c b/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c
index 290339e08..4e717159f 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c
@@ -29,8 +29,6 @@ stream_flags_encode(const lzma_stream_flags *options, uint8_t *out)
extern LZMA_API(lzma_ret)
lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
{
- uint32_t crc;
-
assert(sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE
+ 4 == LZMA_STREAM_HEADER_SIZE);
@@ -45,7 +43,7 @@ lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
return LZMA_PROG_ERROR;
// CRC32 of the Stream Header
- crc = lzma_crc32(out + sizeof(lzma_header_magic),
+ const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic),
LZMA_STREAM_FLAGS_SIZE, 0);
unaligned_write32le(out + sizeof(lzma_header_magic)
@@ -58,8 +56,6 @@ lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
extern LZMA_API(lzma_ret)
lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
{
- uint32_t crc;
-
assert(2 * 4 + LZMA_STREAM_FLAGS_SIZE + sizeof(lzma_footer_magic)
== LZMA_STREAM_HEADER_SIZE);
@@ -77,7 +73,7 @@ lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
return LZMA_PROG_ERROR;
// CRC32
- crc = lzma_crc32(
+ const uint32_t crc = lzma_crc32(
out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0);
unaligned_write32le(out, crc);
diff --git a/Utilities/cmliblzma/liblzma/common/vli_decoder.c b/Utilities/cmliblzma/liblzma/common/vli_decoder.c
index 1c663844f..c181828bf 100644
--- a/Utilities/cmliblzma/liblzma/common/vli_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/vli_decoder.c
@@ -14,8 +14,8 @@
extern LZMA_API(lzma_ret)
-lzma_vli_decode(lzma_vli *LZMA_RESTRICT vli, size_t *vli_pos,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size)
{
// If we haven't been given vli_pos, work in single-call mode.
diff --git a/Utilities/cmliblzma/liblzma/common/vli_encoder.c b/Utilities/cmliblzma/liblzma/common/vli_encoder.c
index 09e90cbd7..f8642694e 100644
--- a/Utilities/cmliblzma/liblzma/common/vli_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/vli_encoder.c
@@ -15,7 +15,7 @@
extern LZMA_API(lzma_ret)
lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size)
{
// If we haven't been given vli_pos, work in single-call mode.
diff --git a/Utilities/cmliblzma/liblzma/common/vli_size.c b/Utilities/cmliblzma/liblzma/common/vli_size.c
index 8b931e40b..ec1b4fa48 100644
--- a/Utilities/cmliblzma/liblzma/common/vli_size.c
+++ b/Utilities/cmliblzma/liblzma/common/vli_size.c
@@ -16,11 +16,10 @@
extern LZMA_API(uint32_t)
lzma_vli_size(lzma_vli vli)
{
- uint32_t i = 0;
-
if (vli > LZMA_VLI_MAX)
return 0;
+ uint32_t i = 0;
do {
vli >>= 7;
++i;
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_common.c b/Utilities/cmliblzma/liblzma/delta/delta_common.c
index 803e674a1..4768201d1 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_common.c
+++ b/Utilities/cmliblzma/liblzma/delta/delta_common.c
@@ -15,8 +15,9 @@
static void
-delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
+delta_coder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_delta_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
@@ -24,20 +25,21 @@ delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
extern lzma_ret
-lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_delta_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
- const lzma_options_delta *opt;
-
// Allocate memory for the decoder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_delta_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_delta_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
+
// End function is the same for encoder and decoder.
next->end = &delta_coder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Validate the options.
@@ -45,16 +47,15 @@ lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
return LZMA_OPTIONS_ERROR;
// Set the delta distance.
- opt = filters[0].options;
- next->coder->distance = opt->dist;
+ const lzma_options_delta *opt = filters[0].options;
+ coder->distance = opt->dist;
// Initialize the rest of the variables.
- next->coder->pos = 0;
- memzero(next->coder->history, LZMA_DELTA_DIST_MAX);
+ coder->pos = 0;
+ memzero(coder->history, LZMA_DELTA_DIST_MAX);
// Initialize the next decoder in the chain, if any.
- return lzma_next_filter_init(&next->coder->next,
- allocator, filters + 1);
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
@@ -68,5 +69,5 @@ lzma_delta_coder_memusage(const void *options)
|| opt->dist > LZMA_DELTA_DIST_MAX)
return UINT64_MAX;
- return sizeof(lzma_coder);
+ return sizeof(lzma_delta_coder);
}
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_decoder.c b/Utilities/cmliblzma/liblzma/delta/delta_decoder.c
index 28df72735..6859afa5c 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_decoder.c
+++ b/Utilities/cmliblzma/liblzma/delta/delta_decoder.c
@@ -15,12 +15,11 @@
static void
-decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
+decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
{
- size_t i;
const size_t distance = coder->distance;
- for (i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = buffer[i];
}
@@ -28,17 +27,18 @@ decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
static lzma_ret
-delta_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+delta_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
- const size_t out_start = *out_pos;
- lzma_ret ret;
+ lzma_delta_coder *coder = coder_ptr;
assert(coder->next.code != NULL);
- ret = coder->next.code(coder->next.coder, allocator,
+ const size_t out_start = *out_pos;
+
+ const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
@@ -49,7 +49,7 @@ delta_decode(lzma_coder *coder, lzma_allocator *allocator,
extern lzma_ret
-lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
next->code = &delta_decode;
@@ -58,15 +58,14 @@ lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
-lzma_delta_props_decode(void **options, lzma_allocator *allocator,
+lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_delta *opt;
-
if (props_size != 1)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_delta), allocator);
+ lzma_options_delta *opt
+ = lzma_alloc(sizeof(lzma_options_delta), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_decoder.h b/Utilities/cmliblzma/liblzma/delta/delta_decoder.h
index ae89acc59..ad89cc659 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_decoder.h
+++ b/Utilities/cmliblzma/liblzma/delta/delta_decoder.h
@@ -16,10 +16,11 @@
#include "delta_common.h"
extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_delta_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_encoder.c b/Utilities/cmliblzma/liblzma/delta/delta_encoder.c
index a39c154f1..384165151 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_encoder.c
+++ b/Utilities/cmliblzma/liblzma/delta/delta_encoder.c
@@ -18,13 +18,12 @@
/// is the first filter in the chain (and thus the last filter in the
/// encoder's filter stack).
static void
-copy_and_encode(lzma_coder *coder,
- const uint8_t *LZMA_RESTRICT in, uint8_t *LZMA_RESTRICT out, size_t size)
+copy_and_encode(lzma_delta_coder *coder,
+ const uint8_t *restrict in, uint8_t *restrict out, size_t size)
{
- size_t i;
const size_t distance = coder->distance;
- for (i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = in[i];
@@ -36,12 +35,11 @@ copy_and_encode(lzma_coder *coder,
/// Encodes the data in place. This is used when we are the last filter
/// in the chain (and thus non-last filter in the encoder's filter stack).
static void
-encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
+encode_in_place(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
{
- size_t i;
const size_t distance = coder->distance;
- for (i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = buffer[i];
@@ -51,11 +49,13 @@ encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
static lzma_ret
-delta_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+delta_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_delta_coder *coder = coder_ptr;
+
lzma_ret ret;
if (coder->next.code == NULL) {
@@ -86,10 +86,12 @@ delta_encode(lzma_coder *coder, lzma_allocator *allocator,
static lzma_ret
-delta_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+delta_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters_null lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_delta_coder *coder = coder_ptr;
+
// Delta doesn't and will never support changing the options in
// the middle of encoding. If the app tries to change them, we
// simply ignore them.
@@ -99,7 +101,7 @@ delta_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
extern lzma_ret
-lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_delta_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
next->code = &delta_encode;
@@ -111,13 +113,12 @@ lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
lzma_delta_props_encode(const void *options, uint8_t *out)
{
- const lzma_options_delta *opt = options;
-
// The caller must have already validated the options, so it's
// LZMA_PROG_ERROR if they are invalid.
if (lzma_delta_coder_memusage(options) == UINT64_MAX)
return LZMA_PROG_ERROR;
+ const lzma_options_delta *opt = options;
out[0] = opt->dist - LZMA_DELTA_DIST_MIN;
return LZMA_OK;
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_encoder.h b/Utilities/cmliblzma/liblzma/delta/delta_encoder.h
index a447862f2..4ab984785 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_encoder.h
+++ b/Utilities/cmliblzma/liblzma/delta/delta_encoder.h
@@ -16,7 +16,8 @@
#include "delta_common.h"
extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out);
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_private.h b/Utilities/cmliblzma/liblzma/delta/delta_private.h
index 62b7fed86..0d6cb3866 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_private.h
+++ b/Utilities/cmliblzma/liblzma/delta/delta_private.h
@@ -15,7 +15,7 @@
#include "delta_common.h"
-struct lzma_coder_s {
+typedef struct {
/// Next coder in the chain
lzma_next_coder next;
@@ -27,11 +27,11 @@ struct lzma_coder_s {
/// Buffer to hold history of the original data
uint8_t history[LZMA_DELTA_DIST_MAX];
-};
+} lzma_delta_coder;
extern lzma_ret lzma_delta_coder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters);
#endif
diff --git a/Utilities/cmliblzma/liblzma/liblzma.pc.in b/Utilities/cmliblzma/liblzma/liblzma.pc.in
index 7f11f1a20..9fa489115 100644
--- a/Utilities/cmliblzma/liblzma/liblzma.pc.in
+++ b/Utilities/cmliblzma/liblzma/liblzma.pc.in
@@ -16,4 +16,4 @@ URL: @PACKAGE_URL@
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -llzma
-Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Libs.private: @PTHREAD_CFLAGS@ @LIBS@
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_decoder.c b/Utilities/cmliblzma/liblzma/lz/lz_decoder.c
index 9fa1bdc3a..c7086440b 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_decoder.c
+++ b/Utilities/cmliblzma/liblzma/lz/lz_decoder.c
@@ -20,7 +20,7 @@
#include "lz_decoder.h"
-struct lzma_coder_s {
+typedef struct {
/// Dictionary (history buffer)
lzma_dict dict;
@@ -48,7 +48,7 @@ struct lzma_coder_s {
size_t size;
uint8_t buffer[LZMA_BUFFER_SIZE];
} temp;
-};
+} lzma_coder;
static void
@@ -64,22 +64,18 @@ lz_decoder_reset(lzma_coder *coder)
static lzma_ret
decode_buffer(lzma_coder *coder,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size)
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size)
{
while (true) {
- size_t copy_size;
- size_t dict_start;
- lzma_ret ret;
-
// Wrap the dictionary if needed.
if (coder->dict.pos == coder->dict.size)
coder->dict.pos = 0;
// Store the current dictionary position. It is needed to know
// where to start copying to the out[] buffer.
- dict_start = coder->dict.pos;
+ const size_t dict_start = coder->dict.pos;
// Calculate how much we allow coder->lz.code() to decode.
// It must not decode past the end of the dictionary
@@ -90,13 +86,13 @@ decode_buffer(lzma_coder *coder,
coder->dict.size - coder->dict.pos);
// Call the coder->lz.code() to do the actual decoding.
- ret = coder->lz.code(
+ const lzma_ret ret = coder->lz.code(
coder->lz.coder, &coder->dict,
in, in_pos, in_size);
// Copy the decoded data from the dictionary to the out[]
// buffer.
- copy_size = coder->dict.pos - dict_start;
+ const size_t copy_size = coder->dict.pos - dict_start;
assert(copy_size <= out_size - *out_pos);
memcpy(out + *out_pos, coder->dict.buf + dict_start,
copy_size);
@@ -129,13 +125,15 @@ decode_buffer(lzma_coder *coder,
static lzma_ret
-lz_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+lz_decode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action)
{
+ lzma_coder *coder = coder_ptr;
+
if (coder->next.code == NULL)
return decode_buffer(coder, in, in_pos, in_size,
out, out_pos, out_size);
@@ -143,15 +141,13 @@ lz_decode(lzma_coder *coder,
// We aren't the last coder in the chain, we need to decode
// our input to a temporary buffer.
while (*out_pos < out_size) {
- lzma_ret ret;
-
// Fill the temporary buffer if it is empty.
if (!coder->next_finished
&& coder->temp.pos == coder->temp.size) {
coder->temp.pos = 0;
coder->temp.size = 0;
- ret = coder->next.code(
+ const lzma_ret ret = coder->next.code(
coder->next.coder,
allocator, in, in_pos, in_size,
coder->temp.buffer, &coder->temp.size,
@@ -173,7 +169,7 @@ lz_decode(lzma_coder *coder,
return LZMA_OK;
}
- ret = decode_buffer(coder, coder->temp.buffer,
+ const lzma_ret ret = decode_buffer(coder, coder->temp.buffer,
&coder->temp.pos, coder->temp.size,
out, out_pos, out_size);
@@ -190,8 +186,10 @@ lz_decode(lzma_coder *coder,
static void
-lz_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lz_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_coder *coder = coder_ptr;
+
lzma_next_end(&coder->next, allocator);
lzma_free(coder->dict.buf, allocator);
@@ -206,32 +204,33 @@ lz_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
extern lzma_ret
-lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_decoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options))
{
- lzma_lz_options lz_options;
-
// Allocate the base structure if it isn't already allocated.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &lz_decode;
next->end = &lz_decoder_end;
- next->coder->dict.buf = NULL;
- next->coder->dict.size = 0;
- next->coder->lz = LZMA_LZ_DECODER_INIT;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->dict.buf = NULL;
+ coder->dict.size = 0;
+ coder->lz = LZMA_LZ_DECODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Allocate and initialize the LZ-based decoder. It will also give
// us the dictionary size.
- return_if_error(lz_init(&next->coder->lz, allocator,
+ lzma_lz_options lz_options;
+ return_if_error(lz_init(&coder->lz, allocator,
filters[0].options, &lz_options));
// If the dictionary size is very small, increase it to 4096 bytes.
@@ -255,14 +254,14 @@ lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15));
// Allocate and initialize the dictionary.
- if (next->coder->dict.size != lz_options.dict_size) {
- lzma_free(next->coder->dict.buf, allocator);
- next->coder->dict.buf
+ if (coder->dict.size != lz_options.dict_size) {
+ lzma_free(coder->dict.buf, allocator);
+ coder->dict.buf
= lzma_alloc(lz_options.dict_size, allocator);
- if (next->coder->dict.buf == NULL)
+ if (coder->dict.buf == NULL)
return LZMA_MEM_ERROR;
- next->coder->dict.size = lz_options.dict_size;
+ coder->dict.size = lz_options.dict_size;
}
lz_decoder_reset(next->coder);
@@ -275,21 +274,20 @@ lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const size_t copy_size = my_min(lz_options.preset_dict_size,
lz_options.dict_size);
const size_t offset = lz_options.preset_dict_size - copy_size;
- memcpy(next->coder->dict.buf, lz_options.preset_dict + offset,
+ memcpy(coder->dict.buf, lz_options.preset_dict + offset,
copy_size);
- next->coder->dict.pos = copy_size;
- next->coder->dict.full = copy_size;
+ coder->dict.pos = copy_size;
+ coder->dict.full = copy_size;
}
// Miscellaneous initializations
- next->coder->next_finished = false;
- next->coder->this_finished = false;
- next->coder->temp.pos = 0;
- next->coder->temp.size = 0;
+ coder->next_finished = false;
+ coder->this_finished = false;
+ coder->temp.pos = 0;
+ coder->temp.size = 0;
// Initialize the next filter in the chain, if any.
- return lzma_next_filter_init(&next->coder->next, allocator,
- filters + 1);
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
@@ -301,7 +299,8 @@ lzma_lz_decoder_memusage(size_t dictionary_size)
extern void
-lzma_lz_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+lzma_lz_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
{
+ lzma_coder *coder = coder_ptr;
coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size);
}
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_decoder.h b/Utilities/cmliblzma/liblzma/lz/lz_decoder.h
index 76011f2ad..754ccf37c 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_decoder.h
+++ b/Utilities/cmliblzma/liblzma/lz/lz_decoder.h
@@ -53,45 +53,45 @@ typedef struct {
typedef struct {
/// Data specific to the LZ-based decoder
- lzma_coder *coder;
+ void *coder;
/// Function to decode from in[] to *dict
- lzma_ret (*code)(lzma_coder *LZMA_RESTRICT coder,
- lzma_dict *LZMA_RESTRICT dict, const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size);
+ lzma_ret (*code)(void *coder,
+ lzma_dict *restrict dict, const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size);
- void (*reset)(lzma_coder *coder, const void *options);
+ void (*reset)(void *coder, const void *options);
/// Set the uncompressed size
- void (*set_uncompressed)(lzma_coder *coder,
- lzma_vli uncompressed_size);
+ void (*set_uncompressed)(void *coder, lzma_vli uncompressed_size);
/// Free allocated resources
- void (*end)(lzma_coder *coder, lzma_allocator *allocator);
+ void (*end)(void *coder, const lzma_allocator *allocator);
} lzma_lz_decoder;
-static const lzma_lz_decoder LZMA_LZ_DECODER_INIT =
- {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- };
+#define LZMA_LZ_DECODER_INIT \
+ (lzma_lz_decoder){ \
+ .coder = NULL, \
+ .code = NULL, \
+ .reset = NULL, \
+ .set_uncompressed = NULL, \
+ .end = NULL, \
+ }
extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters,
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_decoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options));
extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size);
extern void lzma_lz_decoder_uncompressed(
- lzma_coder *coder, lzma_vli uncompressed_size);
+ void *coder, lzma_vli uncompressed_size);
//////////////////////
@@ -151,15 +151,13 @@ dict_repeat(lzma_dict *dict, uint32_t distance, uint32_t *len)
dict->pos += left;
} else {
- uint32_t copy_pos;
- uint32_t copy_size;
-
// The bigger the dictionary, the more rare this
// case occurs. We need to "wrap" the dict, thus
// we might need two memcpy() to copy all the data.
assert(dict->full == dict->size);
- copy_pos = dict->pos - distance - 1 + dict->size;
- copy_size = dict->size - copy_pos;
+ const uint32_t copy_pos
+ = dict->pos - distance - 1 + dict->size;
+ uint32_t copy_size = dict->size - copy_pos;
if (copy_size < left) {
memmove(dict->buf + dict->pos, dict->buf + copy_pos,
@@ -202,9 +200,9 @@ dict_put(lzma_dict *dict, uint8_t byte)
/// Copies arbitrary amount of data into the dictionary.
static inline void
-dict_write(lzma_dict *LZMA_RESTRICT dict, const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size,
- size_t *LZMA_RESTRICT left)
+dict_write(lzma_dict *restrict dict, const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size,
+ size_t *restrict left)
{
// NOTE: If we are being given more data than the size of the
// dictionary, it could be possible to optimize the LZ decoder
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_encoder.c b/Utilities/cmliblzma/liblzma/lz/lz_encoder.c
index 1dae924b4..9a74b7c47 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_encoder.c
+++ b/Utilities/cmliblzma/liblzma/lz/lz_encoder.c
@@ -20,8 +20,10 @@
# include "lz_encoder_hash_table.h"
#endif
+#include "memcmplen.h"
-struct lzma_coder_s {
+
+typedef struct {
/// LZ-based encoder e.g. LZMA
lzma_lz_encoder lz;
@@ -30,7 +32,7 @@ struct lzma_coder_s {
/// Next coder in the chain
lzma_next_coder next;
-};
+} lzma_coder;
/// \brief Moves the data in the input window to free space for new data
@@ -43,18 +45,16 @@ struct lzma_coder_s {
static void
move_window(lzma_mf *mf)
{
- uint32_t move_offset;
- size_t move_size;
-
// Align the move to a multiple of 16 bytes. Some LZ-based encoders
// like LZMA use the lowest bits of mf->read_pos to know the
// alignment of the uncompressed data. We also get better speed
// for memmove() with aligned buffers.
assert(mf->read_pos > mf->keep_size_before);
- move_offset = (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
+ const uint32_t move_offset
+ = (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
assert(mf->write_pos > move_offset);
- move_size = mf->write_pos - move_offset;
+ const size_t move_size = mf->write_pos - move_offset;
assert(move_offset + move_size <= mf->size);
@@ -78,12 +78,10 @@ move_window(lzma_mf *mf)
/// This function must not be called once it has returned LZMA_STREAM_END.
///
static lzma_ret
-fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
- size_t *in_pos, size_t in_size, lzma_action action)
+fill_window(lzma_coder *coder, const lzma_allocator *allocator,
+ const uint8_t *in, size_t *in_pos, size_t in_size,
+ lzma_action action)
{
- size_t write_pos;
- lzma_ret ret;
-
assert(coder->mf.read_pos <= coder->mf.write_pos);
// Move the sliding window if needed.
@@ -93,7 +91,8 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
// Maybe this is ugly, but lzma_mf uses uint32_t for most things
// (which I find cleanest), but we need size_t here when filling
// the history window.
- write_pos = coder->mf.write_pos;
+ size_t write_pos = coder->mf.write_pos;
+ lzma_ret ret;
if (coder->next.code == NULL) {
// Not using a filter, simply memcpy() as much as possible.
lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer,
@@ -111,6 +110,12 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
coder->mf.write_pos = write_pos;
+ // Silence Valgrind. lzma_memcmplen() can read extra bytes
+ // and Valgrind will give warnings if those bytes are uninitialized
+ // because Valgrind cannot see that the values of the uninitialized
+ // bytes are eventually ignored.
+ memzero(coder->mf.buffer + write_pos, LZMA_MEMCMPLEN_EXTRA);
+
// If end of stream has been reached or flushing completed, we allow
// the encoder to process all the input (that is, read_pos is allowed
// to reach write_pos). Otherwise we keep keep_size_after bytes
@@ -134,7 +139,7 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
&& coder->mf.read_pos < coder->mf.read_limit) {
// Match finder may update coder->pending and expects it to
// start from zero, so use a temporary variable.
- const size_t pending = coder->mf.pending;
+ const uint32_t pending = coder->mf.pending;
coder->mf.pending = 0;
// Rewind read_pos so that the match finder can hash
@@ -152,16 +157,16 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
static lzma_ret
-lz_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+lz_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size, lzma_action action)
{
+ lzma_coder *coder = coder_ptr;
+
while (*out_pos < out_size
&& (*in_pos < in_size || action != LZMA_RUN)) {
- lzma_ret ret;
-
// Read more data to coder->mf.buffer if needed.
if (coder->mf.action == LZMA_RUN && coder->mf.read_pos
>= coder->mf.read_limit)
@@ -169,7 +174,7 @@ lz_encode(lzma_coder *coder, lzma_allocator *allocator,
in, in_pos, in_size, action));
// Encode
- ret = coder->lz.code(coder->lz.coder,
+ const lzma_ret ret = coder->lz.code(coder->lz.coder,
&coder->mf, out, out_pos, out_size);
if (ret != LZMA_OK) {
// Setting this to LZMA_RUN for cases when we are
@@ -185,17 +190,9 @@ lz_encode(lzma_coder *coder, lzma_allocator *allocator,
static bool
-lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
+lz_encoder_prepare(lzma_mf *mf, const lzma_allocator *allocator,
const lzma_lz_options *lz_options)
{
- bool is_bt;
- uint32_t new_count;
- uint32_t reserve;
- uint32_t old_size;
- uint32_t hash_bytes;
- uint32_t hs;
- uint32_t old_count;
-
// For now, the dictionary size is limited to 1.5 GiB. This may grow
// in the future if needed, but it needs a little more work than just
// changing this check.
@@ -221,14 +218,14 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
// to size_t.
// - Memory usage calculation needs something too, e.g. use uint64_t
// for mf->size.
- reserve = lz_options->dict_size / 2;
+ uint32_t reserve = lz_options->dict_size / 2;
if (reserve > (UINT32_C(1) << 30))
reserve /= 2;
reserve += (lz_options->before_size + lz_options->match_len_max
+ lz_options->after_size) / 2 + (UINT32_C(1) << 19);
- old_size = mf->size;
+ const uint32_t old_size = mf->size;
mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
// Deallocate the old history buffer if it exists but has different
@@ -298,11 +295,12 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
// Calculate the sizes of mf->hash and mf->son and check that
// nice_len is big enough for the selected match finder.
- hash_bytes = lz_options->match_finder & 0x0F;
+ const uint32_t hash_bytes = lz_options->match_finder & 0x0F;
if (hash_bytes > mf->nice_len)
return true;
- is_bt = (lz_options->match_finder & 0x10) != 0;
+ const bool is_bt = (lz_options->match_finder & 0x10) != 0;
+ uint32_t hs;
if (hash_bytes == 2) {
hs = 0xFFFF;
@@ -338,25 +336,22 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
hs += HASH_4_SIZE;
*/
- // If the above code calculating hs is modified, make sure that
- // this assertion stays valid (UINT32_MAX / 5 is not strictly the
- // exact limit). If it doesn't, you need to calculate that
- // hash_size_sum + sons_count cannot overflow.
- assert(hs < UINT32_MAX / 5);
-
- old_count = mf->hash_size_sum + mf->sons_count;
- mf->hash_size_sum = hs;
+ const uint32_t old_hash_count = mf->hash_count;
+ const uint32_t old_sons_count = mf->sons_count;
+ mf->hash_count = hs;
mf->sons_count = mf->cyclic_size;
if (is_bt)
mf->sons_count *= 2;
- new_count = mf->hash_size_sum + mf->sons_count;
-
// Deallocate the old hash array if it exists and has different size
// than what is needed now.
- if (old_count != new_count) {
+ if (old_hash_count != mf->hash_count
+ || old_sons_count != mf->sons_count) {
lzma_free(mf->hash, allocator);
mf->hash = NULL;
+
+ lzma_free(mf->son, allocator);
+ mf->son = NULL;
}
// Maximum number of match finder cycles
@@ -373,16 +368,23 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
static bool
-lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
+lz_encoder_init(lzma_mf *mf, const lzma_allocator *allocator,
const lzma_lz_options *lz_options)
{
- size_t alloc_count;
-
// Allocate the history buffer.
if (mf->buffer == NULL) {
- mf->buffer = lzma_alloc(mf->size, allocator);
+ // lzma_memcmplen() is used for the dictionary buffer
+ // so we need to allocate a few extra bytes to prevent
+ // it from reading past the end of the buffer.
+ mf->buffer = lzma_alloc(mf->size + LZMA_MEMCMPLEN_EXTRA,
+ allocator);
if (mf->buffer == NULL)
return true;
+
+ // Keep Valgrind happy with lzma_memcmplen() and initialize
+ // the extra bytes whose value may get read but which will
+ // effectively get ignored.
+ memzero(mf->buffer + mf->size, LZMA_MEMCMPLEN_EXTRA);
}
// Use cyclic_size as initial mf->offset. This allows
@@ -396,43 +398,48 @@ lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
mf->write_pos = 0;
mf->pending = 0;
- // Allocate match finder's hash array.
- alloc_count = mf->hash_size_sum + mf->sons_count;
-
#if UINT32_MAX >= SIZE_MAX / 4
// Check for integer overflow. (Huge dictionaries are not
// possible on 32-bit CPU.)
- if (alloc_count > SIZE_MAX / sizeof(uint32_t))
+ if (mf->hash_count > SIZE_MAX / sizeof(uint32_t)
+ || mf->sons_count > SIZE_MAX / sizeof(uint32_t))
return true;
#endif
+ // Allocate and initialize the hash table. Since EMPTY_HASH_VALUE
+ // is zero, we can use lzma_alloc_zero() or memzero() for mf->hash.
+ //
+ // We don't need to initialize mf->son, but not doing that may
+ // make Valgrind complain in normalization (see normalize() in
+ // lz_encoder_mf.c). Skipping the initialization is *very* good
+ // when big dictionary is used but only small amount of data gets
+ // actually compressed: most of the mf->son won't get actually
+ // allocated by the kernel, so we avoid wasting RAM and improve
+ // initialization speed a lot.
if (mf->hash == NULL) {
- mf->hash = lzma_alloc(alloc_count * sizeof(uint32_t),
+ mf->hash = lzma_alloc_zero(mf->hash_count * sizeof(uint32_t),
+ allocator);
+ mf->son = lzma_alloc(mf->sons_count * sizeof(uint32_t),
allocator);
- if (mf->hash == NULL)
- return true;
- }
- mf->son = mf->hash + mf->hash_size_sum;
- mf->cyclic_pos = 0;
+ if (mf->hash == NULL || mf->son == NULL) {
+ lzma_free(mf->hash, allocator);
+ mf->hash = NULL;
+
+ lzma_free(mf->son, allocator);
+ mf->son = NULL;
- // Initialize the hash table. Since EMPTY_HASH_VALUE is zero, we
- // can use memset().
+ return true;
+ }
+ } else {
/*
- for (uint32_t i = 0; i < hash_size_sum; ++i)
- mf->hash[i] = EMPTY_HASH_VALUE;
+ for (uint32_t i = 0; i < mf->hash_count; ++i)
+ mf->hash[i] = EMPTY_HASH_VALUE;
*/
- memzero(mf->hash, (size_t)(mf->hash_size_sum) * sizeof(uint32_t));
+ memzero(mf->hash, mf->hash_count * sizeof(uint32_t));
+ }
- // We don't need to initialize mf->son, but not doing that will
- // make Valgrind complain in normalization (see normalize() in
- // lz_encoder_mf.c).
- //
- // Skipping this initialization is *very* good when big dictionary is
- // used but only small amount of data gets actually compressed: most
- // of the mf->hash won't get actually allocated by the kernel, so
- // we avoid wasting RAM and improve initialization speed a lot.
- //memzero(mf->son, (size_t)(mf->sons_count) * sizeof(uint32_t));
+ mf->cyclic_pos = 0;
// Handle preset dictionary.
if (lz_options->preset_dict != NULL
@@ -457,24 +464,32 @@ extern uint64_t
lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
{
// Old buffers must not exist when calling lz_encoder_prepare().
- lzma_mf mf = { NULL };
+ lzma_mf mf = {
+ .buffer = NULL,
+ .hash = NULL,
+ .son = NULL,
+ .hash_count = 0,
+ .sons_count = 0,
+ };
// Setup the size information into mf.
if (lz_encoder_prepare(&mf, NULL, lz_options))
return UINT64_MAX;
// Calculate the memory usage.
- return (uint64_t)(mf.hash_size_sum + mf.sons_count)
- * sizeof(uint32_t)
- + (uint64_t)(mf.size) + sizeof(lzma_coder);
+ return ((uint64_t)(mf.hash_count) + mf.sons_count) * sizeof(uint32_t)
+ + mf.size + sizeof(lzma_coder);
}
static void
-lz_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lz_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_coder *coder = coder_ptr;
+
lzma_next_end(&coder->next, allocator);
+ lzma_free(coder->mf.son, allocator);
lzma_free(coder->mf.hash, allocator);
lzma_free(coder->mf.buffer, allocator);
@@ -489,10 +504,12 @@ lz_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+lz_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters_null lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_coder *coder = coder_ptr;
+
if (coder->lz.options_update == NULL)
return LZMA_PROG_ERROR;
@@ -505,58 +522,63 @@ lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
extern lzma_ret
-lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_encoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options))
{
- lzma_lz_options lz_options;
-
#ifdef HAVE_SMALL
// We need that the CRC32 table has been initialized.
lzma_crc32_init();
#endif
// Allocate and initialize the base data structure.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &lz_encode;
next->end = &lz_encoder_end;
next->update = &lz_encoder_update;
- next->coder->lz.coder = NULL;
- next->coder->lz.code = NULL;
- next->coder->lz.end = NULL;
-
- next->coder->mf.buffer = NULL;
- next->coder->mf.hash = NULL;
- next->coder->mf.hash_size_sum = 0;
- next->coder->mf.sons_count = 0;
-
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->lz.coder = NULL;
+ coder->lz.code = NULL;
+ coder->lz.end = NULL;
+
+ // mf.size is initialized to silence Valgrind
+ // when used on optimized binaries (GCC may reorder
+ // code in a way that Valgrind gets unhappy).
+ coder->mf.buffer = NULL;
+ coder->mf.size = 0;
+ coder->mf.hash = NULL;
+ coder->mf.son = NULL;
+ coder->mf.hash_count = 0;
+ coder->mf.sons_count = 0;
+
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Initialize the LZ-based encoder.
- return_if_error(lz_init(&next->coder->lz, allocator,
+ lzma_lz_options lz_options;
+ return_if_error(lz_init(&coder->lz, allocator,
filters[0].options, &lz_options));
- // Setup the size information into next->coder->mf and deallocate
+ // Setup the size information into coder->mf and deallocate
// old buffers if they have wrong size.
- if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
+ if (lz_encoder_prepare(&coder->mf, allocator, &lz_options))
return LZMA_OPTIONS_ERROR;
// Allocate new buffers if needed, and do the rest of
// the initialization.
- if (lz_encoder_init(&next->coder->mf, allocator, &lz_options))
+ if (lz_encoder_init(&coder->mf, allocator, &lz_options))
return LZMA_MEM_ERROR;
// Initialize the next filter in the chain, if any.
- return lzma_next_filter_init(&next->coder->next, allocator,
- filters + 1);
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_encoder.h b/Utilities/cmliblzma/liblzma/lz/lz_encoder.h
index dcb4b2c5b..426dcd8a3 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_encoder.h
+++ b/Utilities/cmliblzma/liblzma/lz/lz_encoder.h
@@ -119,7 +119,7 @@ struct lzma_mf_s {
lzma_action action;
/// Number of elements in hash[]
- uint32_t hash_size_sum;
+ uint32_t hash_count;
/// Number of elements in son[]
uint32_t sons_count;
@@ -191,19 +191,18 @@ typedef struct {
typedef struct {
/// Data specific to the LZ-based encoder
- lzma_coder *coder;
+ void *coder;
/// Function to encode from *dict to out[]
- lzma_ret (*code)(lzma_coder *LZMA_RESTRICT coder,
- lzma_mf *LZMA_RESTRICT mf, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size);
+ lzma_ret (*code)(void *coder,
+ lzma_mf *restrict mf, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size);
/// Free allocated resources
- void (*end)(lzma_coder *coder, lzma_allocator *allocator);
+ void (*end)(void *coder, const lzma_allocator *allocator);
/// Update the options in the middle of the encoding.
- lzma_ret (*options_update)(lzma_coder *coder,
- const lzma_filter *filter);
+ lzma_ret (*options_update)(void *coder, const lzma_filter *filter);
} lzma_lz_encoder;
@@ -218,7 +217,7 @@ typedef struct {
/// Get pointer to the first byte not ran through the match finder
-static inline uint8_t *
+static inline const uint8_t *
mf_ptr(const lzma_mf *mf)
{
return mf->buffer + mf->read_pos;
@@ -296,10 +295,10 @@ mf_read(lzma_mf *mf, uint8_t *out, size_t *out_pos, size_t out_size,
extern lzma_ret lzma_lz_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_encoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options));
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h b/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h
index de17c54fc..342a333d1 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h
+++ b/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h
@@ -39,22 +39,25 @@
// Endianness doesn't matter in hash_2_calc() (no effect on the output).
#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
# define hash_2_calc() \
- hash_value = *(const uint16_t *)(cur)
+ const uint32_t hash_value = *(const uint16_t *)(cur)
#else
# define hash_2_calc() \
- hash_value = (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)
+ const uint32_t hash_value \
+ = (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)
#endif
#define hash_3_calc() \
- temp = hash_table[cur[0]] ^ cur[1]; \
- hash_2_value = temp & HASH_2_MASK; \
- hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask
+ const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+ const uint32_t hash_2_value = temp & HASH_2_MASK; \
+ const uint32_t hash_value \
+ = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask
#define hash_4_calc() \
- temp = hash_table[cur[0]] ^ cur[1]; \
- hash_2_value = temp & HASH_2_MASK; \
- hash_3_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
- hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \
+ const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+ const uint32_t hash_2_value = temp & HASH_2_MASK; \
+ const uint32_t hash_3_value \
+ = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+ const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \
^ (hash_table[cur[3]] << 5)) & mf->hash_mask
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c b/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c
index 50c3459aa..78520779f 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c
+++ b/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c
@@ -13,6 +13,7 @@
#include "lz_encoder.h"
#include "lz_encoder_hash.h"
+#include "memcmplen.h"
/// \brief Find matches starting from the current byte
@@ -32,9 +33,8 @@ lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
if (count > 0) {
#ifndef NDEBUG
- uint32_t i;
// Validate the matches.
- for (i = 0; i < count; ++i) {
+ for (uint32_t i = 0; i < count; ++i) {
assert(matches[i].len <= mf->nice_len);
assert(matches[i].dist < mf->read_pos);
assert(memcmp(mf_ptr(mf) - 1,
@@ -50,9 +50,6 @@ lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
// If a match of maximum search length was found, try to
// extend the match to maximum possible length.
if (len_best == mf->nice_len) {
- uint8_t *p1;
- uint8_t *p2;
-
// The limit for the match length is either the
// maximum match length supported by the LZ-based
// encoder or the number of bytes left in the
@@ -63,15 +60,13 @@ lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
// Pointer to the byte we just ran through
// the match finder.
- p1 = mf_ptr(mf) - 1;
+ const uint8_t *p1 = mf_ptr(mf) - 1;
// Pointer to the beginning of the match. We need -1
// here because the match distances are zero based.
- p2 = p1 - matches[count - 1].dist - 1;
+ const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
- while (len_best < limit
- && p1[len_best] == p2[len_best])
- ++len_best;
+ len_best = lzma_memcmplen(p1, p2, len_best, limit);
}
}
@@ -112,36 +107,35 @@ lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
static void
normalize(lzma_mf *mf)
{
- uint32_t i;
- uint32_t subvalue;
- uint32_t count;
- uint32_t *hash;
-
assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS);
// In future we may not want to touch the lowest bits, because there
// may be match finders that use larger resolution than one byte.
- subvalue = (MUST_NORMALIZE_POS - mf->cyclic_size);
+ const uint32_t subvalue
+ = (MUST_NORMALIZE_POS - mf->cyclic_size);
// & (~(UINT32_C(1) << 10) - 1);
- count = mf->hash_size_sum + mf->sons_count;
- hash = mf->hash;
-
- for (i = 0; i < count; ++i) {
+ for (uint32_t i = 0; i < mf->hash_count; ++i) {
// If the distance is greater than the dictionary size,
// we can simply mark the hash element as empty.
+ if (mf->hash[i] <= subvalue)
+ mf->hash[i] = EMPTY_HASH_VALUE;
+ else
+ mf->hash[i] -= subvalue;
+ }
+
+ for (uint32_t i = 0; i < mf->sons_count; ++i) {
+ // Do the same for mf->son.
//
- // NOTE: Only the first mf->hash_size_sum elements are
- // initialized for sure. There may be uninitialized elements
- // in mf->son. Since we go through both mf->hash and
- // mf->son here in normalization, Valgrind may complain
- // that the "if" below depends on uninitialized value. In
- // this case it is safe to ignore the warning. See also the
- // comments in lz_encoder_init() in lz_encoder.c.
- if (hash[i] <= subvalue)
- hash[i] = EMPTY_HASH_VALUE;
+ // NOTE: There may be uninitialized elements in mf->son.
+ // Valgrind may complain that the "if" below depends on
+ // an uninitialized value. In this case it is safe to ignore
+ // the warning. See also the comments in lz_encoder_init()
+ // in lz_encoder.c.
+ if (mf->son[i] <= subvalue)
+ mf->son[i] = EMPTY_HASH_VALUE;
else
- hash[i] -= subvalue;
+ mf->son[i] -= subvalue;
}
// Update offset to match the new locations.
@@ -204,14 +198,15 @@ move_pending(lzma_mf *mf)
move_pending(mf); \
ret_op; \
} \
- cur = mf_ptr(mf); \
- pos = mf->read_pos + mf->offset
+ const uint8_t *cur = mf_ptr(mf); \
+ const uint32_t pos = mf->read_pos + mf->offset
/// Header for find functions. "return 0" indicates that zero matches
/// were found.
#define header_find(is_bt, len_min) \
- header(is_bt, len_min, return 0)
+ header(is_bt, len_min, return 0); \
+ uint32_t matches_count = 0
/// Header for a loop in a skip function. "continue" tells to skip the rest
@@ -268,19 +263,15 @@ hc_find_func(
while (true) {
const uint32_t delta = pos - cur_match;
- const uint8_t *pb;
if (depth-- == 0 || delta >= cyclic_size)
return matches;
- pb = cur - delta;
+ const uint8_t *const pb = cur - delta;
cur_match = son[cyclic_pos - delta
+ (delta > cyclic_pos ? cyclic_size : 0)];
if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
- uint32_t len = 0;
- while (++len != len_limit)
- if (pb[len] != cur[len])
- break;
+ uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
if (len_best < len) {
len_best = len;
@@ -313,27 +304,21 @@ do { \
extern uint32_t
lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t delta2, cur_match;
- uint32_t len_best = 2;
- uint32_t matches_count = 0;
-
header_find(false, 3);
hash_3_calc();
- delta2 = pos - mf->hash[hash_2_value];
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 2;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(cur - delta2, cur,
+ len_best, len_limit);
matches[0].len = len_best;
matches[0].dist = delta2 - 1;
@@ -353,22 +338,18 @@ extern void
lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t cur_match;
-
if (mf_avail(mf) < 3) {
move_pending(mf);
continue;
}
- cur = mf_ptr(mf);
- pos = mf->read_pos + mf->offset;
+ const uint8_t *cur = mf_ptr(mf);
+ const uint32_t pos = mf->read_pos + mf->offset;
hash_3_calc();
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
@@ -384,25 +365,21 @@ lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
extern uint32_t
lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t delta2, delta3, cur_match;
- uint32_t len_best = 1;
- uint32_t matches_count = 0;
-
header_find(false, 4);
hash_4_calc();
- delta2 = pos - mf->hash[hash_2_value];
- delta3 = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t delta3
+ = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+ const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value ] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 1;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
len_best = 2;
matches[0].len = 2;
@@ -418,9 +395,8 @@ lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
}
if (matches_count != 0) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(cur - delta2, cur,
+ len_best, len_limit);
matches[matches_count - 1].len = len_best;
@@ -441,22 +417,18 @@ extern void
lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t cur_match;
-
if (mf_avail(mf) < 4) {
move_pending(mf);
continue;
}
- cur = mf_ptr(mf);
- pos = mf->read_pos + mf->offset;
+ const uint8_t *cur = mf_ptr(mf);
+ const uint32_t pos = mf->read_pos + mf->offset;
hash_4_calc();
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
@@ -494,10 +466,6 @@ bt_find_func(
uint32_t len1 = 0;
while (true) {
- uint32_t *pair;
- const uint8_t *pb;
- uint32_t len;
-
const uint32_t delta = pos - cur_match;
if (depth-- == 0 || delta >= cyclic_size) {
*ptr0 = EMPTY_HASH_VALUE;
@@ -505,17 +473,15 @@ bt_find_func(
return matches;
}
- pair = son + ((cyclic_pos - delta
+ uint32_t *const pair = son + ((cyclic_pos - delta
+ (delta > cyclic_pos ? cyclic_size : 0))
<< 1);
- pb = cur - delta;
- len = my_min(len0, len1);
+ const uint8_t *const pb = cur - delta;
+ uint32_t len = my_min(len0, len1);
if (pb[len] == cur[len]) {
- while (++len != len_limit)
- if (pb[len] != cur[len])
- break;
+ len = lzma_memcmplen(pb, cur, len + 1, len_limit);
if (len_best < len) {
len_best = len;
@@ -564,10 +530,6 @@ bt_skip_func(
uint32_t len1 = 0;
while (true) {
- uint32_t *pair;
- const uint8_t *pb;
- uint32_t len;
-
const uint32_t delta = pos - cur_match;
if (depth-- == 0 || delta >= cyclic_size) {
*ptr0 = EMPTY_HASH_VALUE;
@@ -575,16 +537,14 @@ bt_skip_func(
return;
}
- pair = son + ((cyclic_pos - delta
+ uint32_t *pair = son + ((cyclic_pos - delta
+ (delta > cyclic_pos ? cyclic_size : 0))
<< 1);
- pb = cur - delta;
- len = my_min(len0, len1);
+ const uint8_t *pb = cur - delta;
+ uint32_t len = my_min(len0, len1);
if (pb[len] == cur[len]) {
- while (++len != len_limit)
- if (pb[len] != cur[len])
- break;
+ len = lzma_memcmplen(pb, cur, len + 1, len_limit);
if (len == len_limit) {
*ptr1 = pair[0];
@@ -626,17 +586,11 @@ do { \
extern uint32_t
lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t hash_value; /* hash_2_calc */
- uint32_t cur_match;
- uint32_t matches_count = 0;
-
header_find(true, 2);
hash_2_calc();
- cur_match = mf->hash[hash_value];
+ const uint32_t cur_match = mf->hash[hash_value];
mf->hash[hash_value] = pos;
bt_find(1);
@@ -647,16 +601,11 @@ extern void
lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t hash_value; /* hash_2_calc */
- uint32_t cur_match;
-
header_skip(true, 2);
hash_2_calc();
- cur_match = mf->hash[hash_value];
+ const uint32_t cur_match = mf->hash[hash_value];
mf->hash[hash_value] = pos;
bt_skip();
@@ -670,27 +619,21 @@ lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
extern uint32_t
lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t delta2, cur_match;
- uint32_t len_best = 2;
- uint32_t matches_count = 0;
-
header_find(true, 3);
hash_3_calc();
- delta2 = pos - mf->hash[hash_2_value];
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 2;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(
+ cur, cur - delta2, len_best, len_limit);
matches[0].len = len_best;
matches[0].dist = delta2 - 1;
@@ -710,16 +653,12 @@ extern void
lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t cur_match;
-
header_skip(true, 3);
hash_3_calc();
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
@@ -735,25 +674,21 @@ lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
extern uint32_t
lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t delta2, delta3, cur_match;
- uint32_t len_best = 1;
- uint32_t matches_count = 0;
-
header_find(true, 4);
hash_4_calc();
- delta2 = pos - mf->hash[hash_2_value];
- delta3 = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t delta3
+ = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+ const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 1;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
len_best = 2;
matches[0].len = 2;
@@ -769,9 +704,8 @@ lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
}
if (matches_count != 0) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(
+ cur, cur - delta2, len_best, len_limit);
matches[matches_count - 1].len = len_best;
@@ -792,16 +726,12 @@ extern void
lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t cur_match;
-
header_skip(true, 4);
hash_4_calc();
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
diff --git a/Utilities/cmliblzma/liblzma/lzma/fastpos.h b/Utilities/cmliblzma/liblzma/lzma/fastpos.h
index 5a834d68d..a3feea58d 100644
--- a/Utilities/cmliblzma/liblzma/lzma/fastpos.h
+++ b/Utilities/cmliblzma/liblzma/lzma/fastpos.h
@@ -14,15 +14,15 @@
#ifndef LZMA_FASTPOS_H
#define LZMA_FASTPOS_H
-// LZMA encodes match distances (positions) by storing the highest two
-// bits using a six-bit value [0, 63], and then the missing lower bits.
-// Dictionary size is also stored using this encoding in the new .lzma
+// LZMA encodes match distances by storing the highest two bits using
+// a six-bit value [0, 63], and then the missing lower bits.
+// Dictionary size is also stored using this encoding in the .xz
// file format header.
//
// fastpos.h provides a way to quickly find out the correct six-bit
// values. The following table gives some examples of this encoding:
//
-// pos return
+// dist return
// 0 0
// 1 1
// 2 2
@@ -48,10 +48,10 @@
// Provided functions or macros
// ----------------------------
//
-// get_pos_slot(pos) is the basic version. get_pos_slot_2(pos)
-// assumes that pos >= FULL_DISTANCES, thus the result is at least
-// FULL_DISTANCES_BITS * 2. Using get_pos_slot(pos) instead of
-// get_pos_slot_2(pos) would give the same result, but get_pos_slot_2(pos)
+// get_dist_slot(dist) is the basic version. get_dist_slot_2(dist)
+// assumes that dist >= FULL_DISTANCES, thus the result is at least
+// FULL_DISTANCES_BITS * 2. Using get_dist_slot(dist) instead of
+// get_dist_slot_2(dist) would give the same result, but get_dist_slot_2(dist)
// should be tiny bit faster due to the assumption being made.
//
//
@@ -75,16 +75,15 @@
// on all systems I have tried. The size optimized version is sometimes
// slightly faster, but sometimes it is a lot slower.
-#include "config.h"
-
#ifdef HAVE_SMALL
-# define get_pos_slot(pos) ((pos) <= 4 ? (pos) : get_pos_slot_2(pos))
+# define get_dist_slot(dist) \
+ ((dist) <= 4 ? (dist) : get_dist_slot_2(dist))
static inline uint32_t
-get_pos_slot_2(uint32_t pos)
+get_dist_slot_2(uint32_t dist)
{
- const uint32_t i = bsr32(pos);
- return (i + i) + ((pos >> (i - 1)) & 1);
+ const uint32_t i = bsr32(dist);
+ return (i + i) + ((dist >> (i - 1)) & 1);
}
@@ -101,39 +100,39 @@ extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS];
#define fastpos_limit(extra, n) \
(UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
-#define fastpos_result(pos, extra, n) \
- lzma_fastpos[(pos) >> fastpos_shift(extra, n)] \
+#define fastpos_result(dist, extra, n) \
+ lzma_fastpos[(dist) >> fastpos_shift(extra, n)] \
+ 2 * fastpos_shift(extra, n)
static inline uint32_t
-get_pos_slot(uint32_t pos)
+get_dist_slot(uint32_t dist)
{
// If it is small enough, we can pick the result directly from
// the precalculated table.
- if (pos < fastpos_limit(0, 0))
- return lzma_fastpos[pos];
+ if (dist < fastpos_limit(0, 0))
+ return lzma_fastpos[dist];
- if (pos < fastpos_limit(0, 1))
- return fastpos_result(pos, 0, 1);
+ if (dist < fastpos_limit(0, 1))
+ return fastpos_result(dist, 0, 1);
- return fastpos_result(pos, 0, 2);
+ return fastpos_result(dist, 0, 2);
}
#ifdef FULL_DISTANCES_BITS
static inline uint32_t
-get_pos_slot_2(uint32_t pos)
+get_dist_slot_2(uint32_t dist)
{
- assert(pos >= FULL_DISTANCES);
+ assert(dist >= FULL_DISTANCES);
- if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
- return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 0);
+ if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
+ return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 0);
- if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
- return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 1);
+ if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
+ return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 1);
- return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 2);
+ return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 2);
}
#endif
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c
index bd2a73782..878c870ae 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c
@@ -16,7 +16,7 @@
#include "lzma_decoder.h"
-struct lzma_coder_s {
+typedef struct {
enum sequence {
SEQ_CONTROL,
SEQ_UNCOMPRESSED_1,
@@ -50,14 +50,16 @@ struct lzma_coder_s {
bool need_dictionary_reset;
lzma_options_lzma options;
-};
+} lzma_lzma2_coder;
static lzma_ret
-lzma2_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dict,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+lzma2_decode(void *coder_ptr, lzma_dict *restrict dict,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size)
{
+ lzma_lzma2_coder *restrict coder = coder_ptr;
+
// With SEQ_LZMA it is possible that no new input is needed to do
// some progress. The rest of the sequences assume that there is
// at least one byte of input.
@@ -209,8 +211,10 @@ lzma2_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dict,
static void
-lzma2_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lzma2_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_lzma2_coder *coder = coder_ptr;
+
assert(coder->lzma.end == NULL);
lzma_free(coder->lzma.coder, allocator);
@@ -221,34 +225,36 @@ lzma2_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-lzma2_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
+lzma2_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *opt, lzma_lz_options *lz_options)
{
- const lzma_options_lzma *options = opt;
-
- if (lz->coder == NULL) {
- lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (lz->coder == NULL)
+ lzma_lzma2_coder *coder = lz->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ lz->coder = coder;
lz->code = &lzma2_decode;
lz->end = &lzma2_decoder_end;
- lz->coder->lzma = LZMA_LZ_DECODER_INIT;
+ coder->lzma = LZMA_LZ_DECODER_INIT;
}
- lz->coder->sequence = SEQ_CONTROL;
- lz->coder->need_properties = true;
- lz->coder->need_dictionary_reset = options->preset_dict == NULL
+ const lzma_options_lzma *options = opt;
+
+ coder->sequence = SEQ_CONTROL;
+ coder->need_properties = true;
+ coder->need_dictionary_reset = options->preset_dict == NULL
|| options->preset_dict_size == 0;
- return lzma_lzma_decoder_create(&lz->coder->lzma,
+ return lzma_lzma_decoder_create(&coder->lzma,
allocator, options, lz_options);
}
extern lzma_ret
-lzma_lzma2_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma2_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
// LZMA2 can only be the last filter in the chain. This is enforced
@@ -263,17 +269,15 @@ lzma_lzma2_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern uint64_t
lzma_lzma2_decoder_memusage(const void *options)
{
- return sizeof(lzma_coder)
+ return sizeof(lzma_lzma2_coder)
+ lzma_lzma_decoder_memusage_nocheck(options);
}
extern lzma_ret
-lzma_lzma2_props_decode(void **options, lzma_allocator *allocator,
+lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_lzma *opt;
-
if (props_size != 1)
return LZMA_OPTIONS_ERROR;
@@ -285,7 +289,8 @@ lzma_lzma2_props_decode(void **options, lzma_allocator *allocator,
if (props[0] > 40)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_lzma), allocator);
+ lzma_options_lzma *opt = lzma_alloc(
+ sizeof(lzma_options_lzma), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.h b/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.h
index fac4ac487..ef2dcbfa7 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.h
@@ -17,12 +17,13 @@
#include "common.h"
extern lzma_ret lzma_lzma2_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern uint64_t lzma_lzma2_decoder_memusage(const void *options);
extern lzma_ret lzma_lzma2_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.c
index a3651a7c6..63588ee30 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.c
@@ -17,7 +17,7 @@
#include "lzma2_encoder.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_INIT,
SEQ_LZMA_ENCODE,
@@ -27,7 +27,7 @@ struct lzma_coder_s {
} sequence;
/// LZMA encoder
- lzma_coder *lzma;
+ void *lzma;
/// LZMA options currently in use.
lzma_options_lzma opt_cur;
@@ -48,20 +48,19 @@ struct lzma_coder_s {
/// Buffer to hold the chunk header and LZMA compressed data
uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX];
-};
+} lzma_lzma2_coder;
static void
-lzma2_header_lzma(lzma_coder *coder)
+lzma2_header_lzma(lzma_lzma2_coder *coder)
{
- size_t pos;
- size_t size;
-
assert(coder->uncompressed_size > 0);
assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
assert(coder->compressed_size > 0);
assert(coder->compressed_size <= LZMA2_CHUNK_MAX);
+ size_t pos;
+
if (coder->need_properties) {
pos = 0;
@@ -82,7 +81,7 @@ lzma2_header_lzma(lzma_coder *coder)
coder->buf_pos = pos;
// Uncompressed size
- size = coder->uncompressed_size - 1;
+ size_t size = coder->uncompressed_size - 1;
coder->buf[pos++] += size >> 16;
coder->buf[pos++] = (size >> 8) & 0xFF;
coder->buf[pos++] = size & 0xFF;
@@ -109,7 +108,7 @@ lzma2_header_lzma(lzma_coder *coder)
static void
-lzma2_header_uncompressed(lzma_coder *coder)
+lzma2_header_uncompressed(lzma_lzma2_coder *coder)
{
assert(coder->uncompressed_size > 0);
assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX);
@@ -134,10 +133,12 @@ lzma2_header_uncompressed(lzma_coder *coder)
static lzma_ret
-lzma2_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+lzma2_encode(void *coder_ptr, lzma_mf *restrict mf,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size)
{
+ lzma_lzma2_coder *restrict coder = coder_ptr;
+
while (*out_pos < out_size)
switch (coder->sequence) {
case SEQ_INIT:
@@ -163,9 +164,6 @@ lzma2_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
// Fall through
case SEQ_LZMA_ENCODE: {
- uint32_t read_start;
- lzma_ret ret;
-
// Calculate how much more uncompressed data this chunk
// could accept.
const uint32_t left = LZMA2_UNCOMPRESSED_MAX
@@ -186,10 +184,10 @@ lzma2_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
// Save the start position so that we can update
// coder->uncompressed_size.
- read_start = mf->read_pos - mf->read_ahead;
+ const uint32_t read_start = mf->read_pos - mf->read_ahead;
// Call the LZMA encoder until the chunk is finished.
- ret = lzma_lzma_encode(coder->lzma, mf,
+ const lzma_ret ret = lzma_lzma_encode(coder->lzma, mf,
coder->buf + LZMA2_HEADER_MAX,
&coder->compressed_size,
LZMA2_CHUNK_MAX, limit);
@@ -266,8 +264,9 @@ lzma2_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
static void
-lzma2_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lzma2_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_lzma2_coder *coder = coder_ptr;
lzma_free(coder->lzma, allocator);
lzma_free(coder, allocator);
return;
@@ -275,9 +274,9 @@ lzma2_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
+lzma2_encoder_options_update(void *coder_ptr, const lzma_filter *filter)
{
- lzma_options_lzma *opt;
+ lzma_lzma2_coder *coder = coder_ptr;
// New options can be set only when there is no incomplete chunk.
// This is the case at the beginning of the raw stream and right
@@ -287,7 +286,7 @@ lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
// Look if there are new options. At least for now,
// only lc/lp/pb can be changed.
- opt = filter->options;
+ const lzma_options_lzma *opt = filter->options;
if (coder->opt_cur.lc != opt->lc || coder->opt_cur.lp != opt->lp
|| coder->opt_cur.pb != opt->pb) {
// Validate the options.
@@ -310,36 +309,38 @@ lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
static lzma_ret
-lzma2_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
+lzma2_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
const void *options, lzma_lz_options *lz_options)
{
if (options == NULL)
return LZMA_PROG_ERROR;
- if (lz->coder == NULL) {
- lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (lz->coder == NULL)
+ lzma_lzma2_coder *coder = lz->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ lz->coder = coder;
lz->code = &lzma2_encode;
lz->end = &lzma2_encoder_end;
lz->options_update = &lzma2_encoder_options_update;
- lz->coder->lzma = NULL;
+ coder->lzma = NULL;
}
- lz->coder->opt_cur = *(const lzma_options_lzma *)(options);
+ coder->opt_cur = *(const lzma_options_lzma *)(options);
- lz->coder->sequence = SEQ_INIT;
- lz->coder->need_properties = true;
- lz->coder->need_state_reset = false;
- lz->coder->need_dictionary_reset
- = lz->coder->opt_cur.preset_dict == NULL
- || lz->coder->opt_cur.preset_dict_size == 0;
+ coder->sequence = SEQ_INIT;
+ coder->need_properties = true;
+ coder->need_state_reset = false;
+ coder->need_dictionary_reset
+ = coder->opt_cur.preset_dict == NULL
+ || coder->opt_cur.preset_dict_size == 0;
// Initialize LZMA encoder
- return_if_error(lzma_lzma_encoder_create(&lz->coder->lzma, allocator,
- &lz->coder->opt_cur, lz_options));
+ return_if_error(lzma_lzma_encoder_create(&coder->lzma, allocator,
+ &coder->opt_cur, lz_options));
// Make sure that we will always have enough history available in
// case we need to use uncompressed chunks. They are used when the
@@ -355,7 +356,7 @@ lzma2_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
extern lzma_ret
-lzma_lzma2_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma2_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return lzma_lz_encoder_init(
@@ -370,7 +371,7 @@ lzma_lzma2_encoder_memusage(const void *options)
if (lzma_mem == UINT64_MAX)
return UINT64_MAX;
- return sizeof(lzma_coder) + lzma_mem;
+ return sizeof(lzma_lzma2_coder) + lzma_mem;
}
@@ -393,7 +394,17 @@ lzma_lzma2_props_encode(const void *options, uint8_t *out)
if (d == UINT32_MAX)
out[0] = 40;
else
- out[0] = get_pos_slot(d + 1) - 24;
+ out[0] = get_dist_slot(d + 1) - 24;
return LZMA_OK;
}
+
+
+extern uint64_t
+lzma_lzma2_block_size(const void *options)
+{
+ const lzma_options_lzma *const opt = options;
+
+ // Use at least 1 MiB to keep compression ratio better.
+ return my_max((uint64_t)(opt->dict_size) * 3, UINT64_C(1) << 20);
+}
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.h b/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.h
index ca19ef469..515f18393 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma2_encoder.h
@@ -31,11 +31,13 @@
extern lzma_ret lzma_lzma2_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters);
extern uint64_t lzma_lzma2_encoder_memusage(const void *options);
extern lzma_ret lzma_lzma2_props_encode(const void *options, uint8_t *out);
+extern uint64_t lzma_lzma2_block_size(const void *options);
+
#endif
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_common.h b/Utilities/cmliblzma/liblzma/lzma/lzma_common.h
index 36267dc88..09efd3872 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_common.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_common.h
@@ -129,15 +129,12 @@ static inline void
literal_init(probability (*probs)[LITERAL_CODER_SIZE],
uint32_t lc, uint32_t lp)
{
- uint32_t coders;
- uint32_t i, j;
-
assert(lc + lp <= LZMA_LCLP_MAX);
- coders = 1U << (lc + lp);
+ const uint32_t coders = 1U << (lc + lp);
- for (i = 0; i < coders; ++i)
- for (j = 0; j < LITERAL_CODER_SIZE; ++j)
+ for (uint32_t i = 0; i < coders; ++i)
+ for (uint32_t j = 0; j < LITERAL_CODER_SIZE; ++j)
bit_reset(probs[i][j]);
return;
@@ -174,53 +171,54 @@ literal_init(probability (*probs)[LITERAL_CODER_SIZE],
// Match distance //
////////////////////
-// Different set of probabilities is used for match distances that have very
+// Different sets of probabilities are used for match distances that have very
// short match length: Lengths of 2, 3, and 4 bytes have a separate set of
// probabilities for each length. The matches with longer length use a shared
// set of probabilities.
-#define LEN_TO_POS_STATES 4
+#define DIST_STATES 4
// Macro to get the index of the appropriate probability array.
-#define get_len_to_pos_state(len) \
- ((len) < LEN_TO_POS_STATES + MATCH_LEN_MIN \
+#define get_dist_state(len) \
+ ((len) < DIST_STATES + MATCH_LEN_MIN \
? (len) - MATCH_LEN_MIN \
- : LEN_TO_POS_STATES - 1)
+ : DIST_STATES - 1)
-// The highest two bits of a match distance (pos slot) are encoded using six
-// bits. See fastpos.h for more explanation.
-#define POS_SLOT_BITS 6
-#define POS_SLOTS (1 << POS_SLOT_BITS)
+// The highest two bits of a match distance (distance slot) are encoded
+// using six bits. See fastpos.h for more explanation.
+#define DIST_SLOT_BITS 6
+#define DIST_SLOTS (1 << DIST_SLOT_BITS)
// Match distances up to 127 are fully encoded using probabilities. Since
-// the highest two bits (pos slot) are always encoded using six bits, the
-// distances 0-3 don't need any additional bits to encode, since the pos
-// slot itself is the same as the actual distance. START_POS_MODEL_INDEX
-// indicates the first pos slot where at least one additional bit is needed.
-#define START_POS_MODEL_INDEX 4
+// the highest two bits (distance slot) are always encoded using six bits,
+// the distances 0-3 don't need any additional bits to encode, since the
+// distance slot itself is the same as the actual distance. DIST_MODEL_START
+// indicates the first distance slot where at least one additional bit is
+// needed.
+#define DIST_MODEL_START 4
// Match distances greater than 127 are encoded in three pieces:
-// - pos slot: the highest two bits
+// - distance slot: the highest two bits
// - direct bits: 2-26 bits below the highest two bits
// - alignment bits: four lowest bits
//
// Direct bits don't use any probabilities.
//
-// The pos slot value of 14 is for distances 128-191 (see the table in
+// The distance slot value of 14 is for distances 128-191 (see the table in
// fastpos.h to understand why).
-#define END_POS_MODEL_INDEX 14
+#define DIST_MODEL_END 14
-// Pos slots that indicate a distance <= 127.
-#define FULL_DISTANCES_BITS (END_POS_MODEL_INDEX / 2)
+// Distance slots that indicate a distance <= 127.
+#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
// For match distances greater than 127, only the highest two bits and the
// lowest four bits (alignment) is encoded using probabilities.
#define ALIGN_BITS 4
-#define ALIGN_TABLE_SIZE (1 << ALIGN_BITS)
-#define ALIGN_MASK (ALIGN_TABLE_SIZE - 1)
+#define ALIGN_SIZE (1 << ALIGN_BITS)
+#define ALIGN_MASK (ALIGN_SIZE - 1)
// LZMA remembers the four most recent match distances. Reusing these distances
// tends to take less space than re-encoding the actual distance value.
-#define REP_DISTANCES 4
+#define REPS 4
#endif
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c
index 3c0f39331..d0f29b763 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c
@@ -16,6 +16,12 @@
#include "lzma_decoder.h"
#include "range_decoder.h"
+// The macros unroll loops with switch statements.
+// Silence warnings about missing fall-through comments.
+#if TUKLIB_GNUC_REQ(7, 0)
+# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#endif
+
#ifdef HAVE_SMALL
@@ -114,33 +120,33 @@ do { \
case seq ## _CHOICE: \
rc_if_0(ld.choice, seq ## _CHOICE) { \
rc_update_0(ld.choice); \
- rc_bit_case(ld.low[pos_state][symbol], 0, 0, seq ## _LOW0); \
- rc_bit_case(ld.low[pos_state][symbol], 0, 0, seq ## _LOW1); \
- rc_bit_case(ld.low[pos_state][symbol], 0, 0, seq ## _LOW2); \
+ rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW0); \
+ rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW1); \
+ rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW2); \
target = symbol - LEN_LOW_SYMBOLS + MATCH_LEN_MIN; \
} else { \
rc_update_1(ld.choice); \
case seq ## _CHOICE2: \
rc_if_0(ld.choice2, seq ## _CHOICE2) { \
rc_update_0(ld.choice2); \
- rc_bit_case(ld.mid[pos_state][symbol], 0, 0, \
+ rc_bit_case(ld.mid[pos_state][symbol], , , \
seq ## _MID0); \
- rc_bit_case(ld.mid[pos_state][symbol], 0, 0, \
+ rc_bit_case(ld.mid[pos_state][symbol], , , \
seq ## _MID1); \
- rc_bit_case(ld.mid[pos_state][symbol], 0, 0, \
+ rc_bit_case(ld.mid[pos_state][symbol], , , \
seq ## _MID2); \
target = symbol - LEN_MID_SYMBOLS \
+ MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
} else { \
rc_update_1(ld.choice2); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH0); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH1); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH2); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH3); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH4); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH5); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH6); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH7); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH0); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH1); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH2); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH3); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH4); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH5); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH6); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH7); \
target = symbol - LEN_HIGH_SYMBOLS \
+ MATCH_LEN_MIN \
+ LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \
@@ -161,7 +167,7 @@ typedef struct {
} lzma_length_decoder;
-struct lzma_coder_s {
+typedef struct {
///////////////////
// Probabilities //
///////////////////
@@ -193,15 +199,15 @@ struct lzma_coder_s {
/// Probability tree for the highest two bits of the match distance.
/// There is a separate probability tree for match lengths of
/// 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
- probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
+ probability dist_slot[DIST_STATES][DIST_SLOTS];
/// Probability trees for additional bits for match distance when the
/// distance is in the range [4, 127].
- probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
+ probability pos_special[FULL_DISTANCES - DIST_MODEL_END];
/// Probability tree for the lowest four bits of a match distance
/// that is equal to or greater than 128.
- probability pos_align[ALIGN_TABLE_SIZE];
+ probability pos_align[ALIGN_SIZE];
/// Length of a normal match
lzma_length_decoder match_len_decoder;
@@ -245,8 +251,8 @@ struct lzma_coder_s {
SEQ_LITERAL_WRITE,
SEQ_IS_REP,
seq_len(SEQ_MATCH_LEN),
- seq_6(SEQ_POS_SLOT),
- SEQ_POS_MODEL,
+ seq_6(SEQ_DIST_SLOT),
+ SEQ_DIST_MODEL,
SEQ_DIRECT,
seq_4(SEQ_ALIGN),
SEQ_EOPM,
@@ -277,14 +283,27 @@ struct lzma_coder_s {
/// If decoding a literal: match byte.
/// If decoding a match: length of the match.
uint32_t len;
-};
+} lzma_lzma1_decoder;
static lzma_ret
-lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
- const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size)
+lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
+ const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size)
{
+ lzma_lzma1_decoder *restrict coder = coder_ptr;
+
+ ////////////////////
+ // Initialization //
+ ////////////////////
+
+ {
+ const lzma_ret ret = rc_read_init(
+ &coder->rc, in, in_pos, in_size);
+ if (ret != LZMA_STREAM_END)
+ return ret;
+ }
+
///////////////
// Variables //
///////////////
@@ -331,16 +350,6 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
if (no_eopm && coder->uncompressed_size < dict.limit - dict.pos)
dict.limit = dict.pos + (size_t)(coder->uncompressed_size);
- ////////////////////
- // Initialization //
- ////////////////////
-
- if (!rc_read_init(&coder->rc, in, in_pos, in_size))
- return LZMA_OK;
-
- rc = coder->rc;
- rc_in_pos = *in_pos;
-
// The main decoder loop. The "switch" is used to restart the decoder at
// correct location. Once restarted, the "switch" is no longer used.
switch (coder->sequence)
@@ -356,21 +365,6 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
break;
rc_if_0(coder->is_match[state][pos_state], SEQ_IS_MATCH) {
- static const lzma_lzma_state next_state[] = {
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_MATCH_LIT_LIT,
- STATE_REP_LIT_LIT,
- STATE_SHORTREP_LIT_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT,
- STATE_SHORTREP_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT
- };
-
rc_update_0(coder->is_match[state][pos_state]);
// It's a literal i.e. a single 8-bit byte.
@@ -388,21 +382,16 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
rc_bit(probs[symbol], , , SEQ_LITERAL);
} while (symbol < (1 << 8));
#else
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL0);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL1);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL2);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL3);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL4);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL5);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL6);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL7);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL0);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL1);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL2);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL3);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL4);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL5);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL6);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL7);
#endif
} else {
-#ifndef HAVE_SMALL
- uint32_t match_bit;
- uint32_t subcoder_index;
-#endif
-
// Decode literal with match byte.
//
// We store the byte we compare against
@@ -441,6 +430,8 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
} while (symbol < (1 << 8));
#else
// Unroll the loop.
+ uint32_t match_bit;
+ uint32_t subcoder_index;
# define d(seq) \
case seq: \
@@ -474,6 +465,20 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
// Use a lookup table to update to literal state,
// since compared to other state updates, this would
// need two branches.
+ static const lzma_lzma_state next_state[] = {
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_MATCH_LIT_LIT,
+ STATE_REP_LIT_LIT,
+ STATE_SHORTREP_LIT_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT,
+ STATE_SHORTREP_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT
+ };
state = next_state[state];
case SEQ_LITERAL_WRITE:
@@ -509,28 +514,28 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
// Prepare to decode the highest two bits of the
// match distance.
- probs = coder->pos_slot[get_len_to_pos_state(len)];
+ probs = coder->dist_slot[get_dist_state(len)];
symbol = 1;
#ifdef HAVE_SMALL
- case SEQ_POS_SLOT:
+ case SEQ_DIST_SLOT:
do {
- rc_bit(probs[symbol], , , SEQ_POS_SLOT);
- } while (symbol < POS_SLOTS);
+ rc_bit(probs[symbol], , , SEQ_DIST_SLOT);
+ } while (symbol < DIST_SLOTS);
#else
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT0);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT1);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT2);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT3);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT4);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT5);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT0);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT1);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT2);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT3);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT4);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT5);
#endif
// Get rid of the highest bit that was needed for
// indexing of the probability array.
- symbol -= POS_SLOTS;
+ symbol -= DIST_SLOTS;
assert(symbol <= 63);
- if (symbol < START_POS_MODEL_INDEX) {
+ if (symbol < DIST_MODEL_START) {
// Match distances [0, 3] have only two bits.
rep0 = symbol;
} else {
@@ -540,7 +545,7 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
assert(limit >= 1 && limit <= 30);
rep0 = 2 + (symbol & 1);
- if (symbol < END_POS_MODEL_INDEX) {
+ if (symbol < DIST_MODEL_END) {
// Prepare to decode the low bits for
// a distance of [4, 127].
assert(limit <= 5);
@@ -560,38 +565,38 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
- symbol - 1;
symbol = 1;
offset = 0;
- case SEQ_POS_MODEL:
+ case SEQ_DIST_MODEL:
#ifdef HAVE_SMALL
do {
rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
} while (++offset < limit);
#else
switch (limit) {
case 5:
assert(offset == 0);
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 4:
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 3:
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 2:
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 1:
@@ -601,9 +606,9 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
// rc_bit_last() here to omit
// the unneeded updating of
// "symbol".
- rc_bit_last(probs[symbol], 0,
+ rc_bit_last(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
}
#endif
} else {
@@ -635,19 +640,19 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
} while (++offset < ALIGN_BITS);
#else
case SEQ_ALIGN0:
- rc_bit(coder->pos_align[symbol], 0,
+ rc_bit(coder->pos_align[symbol], ,
rep0 += 1, SEQ_ALIGN0);
case SEQ_ALIGN1:
- rc_bit(coder->pos_align[symbol], 0,
+ rc_bit(coder->pos_align[symbol], ,
rep0 += 2, SEQ_ALIGN1);
case SEQ_ALIGN2:
- rc_bit(coder->pos_align[symbol], 0,
+ rc_bit(coder->pos_align[symbol], ,
rep0 += 4, SEQ_ALIGN2);
case SEQ_ALIGN3:
- // Like in SEQ_POS_MODEL, we don't
+ // Like in SEQ_DIST_MODEL, we don't
// need "symbol" for anything else
// than indexing the probability array.
- rc_bit_last(coder->pos_align[symbol], 0,
+ rc_bit_last(coder->pos_align[symbol], ,
rep0 += 8, SEQ_ALIGN3);
#endif
@@ -732,11 +737,9 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
// is stored to rep0 and rep1, rep2 and rep3
// are updated accordingly.
rc_if_0(coder->is_rep1[state], SEQ_IS_REP1) {
- uint32_t distance;
-
rc_update_0(coder->is_rep1[state]);
- distance = rep1;
+ const uint32_t distance = rep1;
rep1 = rep0;
rep0 = distance;
@@ -745,23 +748,19 @@ lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
case SEQ_IS_REP2:
rc_if_0(coder->is_rep2[state],
SEQ_IS_REP2) {
- uint32_t distance;
-
rc_update_0(coder->is_rep2[
state]);
- distance = rep2;
+ const uint32_t distance = rep2;
rep2 = rep1;
rep1 = rep0;
rep0 = distance;
} else {
- uint32_t distance;
-
rc_update_1(coder->is_rep2[
state]);
- distance = rep3;
+ const uint32_t distance = rep3;
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
@@ -849,26 +848,17 @@ out:
static void
-lzma_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
{
+ lzma_lzma1_decoder *coder = coder_ptr;
coder->uncompressed_size = uncompressed_size;
}
-/*
-extern void
-lzma_lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
-{
- // This is hack.
- (*(lzma_coder **)(coder))->uncompressed_size = uncompressed_size;
-}
-*/
static void
-lzma_decoder_reset(lzma_coder *coder, const void *opt)
+lzma_decoder_reset(void *coder_ptr, const void *opt)
{
- uint32_t i, j, pos_state;
- uint32_t num_pos_states;
-
+ lzma_lzma1_decoder *coder = coder_ptr;
const lzma_options_lzma *options = opt;
// NOTE: We assume that lc/lp/pb are valid since they were
@@ -895,8 +885,8 @@ lzma_decoder_reset(lzma_coder *coder, const void *opt)
rc_reset(coder->rc);
// Bit and bittree decoders
- for (i = 0; i < STATES; ++i) {
- for (j = 0; j <= coder->pos_mask; ++j) {
+ for (uint32_t i = 0; i < STATES; ++i) {
+ for (uint32_t j = 0; j <= coder->pos_mask; ++j) {
bit_reset(coder->is_match[i][j]);
bit_reset(coder->is_rep0_long[i][j]);
}
@@ -907,22 +897,22 @@ lzma_decoder_reset(lzma_coder *coder, const void *opt)
bit_reset(coder->is_rep2[i]);
}
- for (i = 0; i < LEN_TO_POS_STATES; ++i)
- bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
+ for (uint32_t i = 0; i < DIST_STATES; ++i)
+ bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
- for (i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
+ for (uint32_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
bit_reset(coder->pos_special[i]);
bittree_reset(coder->pos_align, ALIGN_BITS);
// Len decoders (also bit/bittree)
- num_pos_states = 1U << options->pb;
+ const uint32_t num_pos_states = 1U << options->pb;
bit_reset(coder->match_len_decoder.choice);
bit_reset(coder->match_len_decoder.choice2);
bit_reset(coder->rep_len_decoder.choice);
bit_reset(coder->rep_len_decoder.choice2);
- for (pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+ for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
bittree_reset(coder->match_len_decoder.low[pos_state],
LEN_LOW_BITS);
bittree_reset(coder->match_len_decoder.mid[pos_state],
@@ -949,13 +939,11 @@ lzma_decoder_reset(lzma_coder *coder, const void *opt)
extern lzma_ret
-lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
+lzma_lzma_decoder_create(lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *opt, lzma_lz_options *lz_options)
{
- const lzma_options_lzma *options = opt;
-
if (lz->coder == NULL) {
- lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ lz->coder = lzma_alloc(sizeof(lzma_lzma1_decoder), allocator);
if (lz->coder == NULL)
return LZMA_MEM_ERROR;
@@ -966,6 +954,7 @@ lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
// All dictionary sizes are OK here. LZ decoder will take care of
// the special cases.
+ const lzma_options_lzma *options = opt;
lz_options->dict_size = options->dict_size;
lz_options->preset_dict = options->preset_dict;
lz_options->preset_dict_size = options->preset_dict_size;
@@ -978,7 +967,7 @@ lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
/// initialization (lzma_lzma_decoder_init() passes function pointer to
/// the LZ initialization).
static lzma_ret
-lzma_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
+lzma_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *options, lzma_lz_options *lz_options)
{
if (!is_lclppb_valid(options))
@@ -995,7 +984,7 @@ lzma_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
extern lzma_ret
-lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
// LZMA can only be the last filter in the chain. This is enforced
@@ -1027,7 +1016,8 @@ extern uint64_t
lzma_lzma_decoder_memusage_nocheck(const void *options)
{
const lzma_options_lzma *const opt = options;
- return sizeof(lzma_coder) + lzma_lz_decoder_memusage(opt->dict_size);
+ return sizeof(lzma_lzma1_decoder)
+ + lzma_lz_decoder_memusage(opt->dict_size);
}
@@ -1042,15 +1032,14 @@ lzma_lzma_decoder_memusage(const void *options)
extern lzma_ret
-lzma_lzma_props_decode(void **options, lzma_allocator *allocator,
+lzma_lzma_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_lzma *opt;
-
if (props_size != 5)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_lzma), allocator);
+ lzma_options_lzma *opt
+ = lzma_alloc(sizeof(lzma_options_lzma), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.h b/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.h
index a463a76fc..fa8ecb23e 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.h
@@ -19,12 +19,13 @@
/// Allocates and initializes LZMA decoder
extern lzma_ret lzma_lzma_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern uint64_t lzma_lzma_decoder_memusage(const void *options);
extern lzma_ret lzma_lzma_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
@@ -40,7 +41,7 @@ extern bool lzma_lzma_lclppb_decode(
/// Allocate and setup function pointers only. This is used by LZMA1 and
/// LZMA2 decoders.
extern lzma_ret lzma_lzma_decoder_create(
- lzma_lz_decoder *lz, lzma_allocator *allocator,
+ lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *opt, lzma_lz_options *lz_options);
/// Gets memory usage without validating lc/lp/pb. This is used by LZMA2
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c
index e8738f411..ba9ce6989 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c
@@ -28,14 +28,11 @@ literal_matched(lzma_range_encoder *rc, probability *subcoder,
symbol += UINT32_C(1) << 8;
do {
- uint32_t match_bit;
- uint32_t subcoder_index;
- uint32_t bit;
-
match_byte <<= 1;
- match_bit = match_byte & offset;
- subcoder_index = offset + match_bit + (symbol >> 8);
- bit = (symbol >> 7) & 1;
+ const uint32_t match_bit = match_byte & offset;
+ const uint32_t subcoder_index
+ = offset + match_bit + (symbol >> 8);
+ const uint32_t bit = (symbol >> 7) & 1;
rc_bit(rc, &subcoder[subcoder_index], bit);
symbol <<= 1;
@@ -46,7 +43,7 @@ literal_matched(lzma_range_encoder *rc, probability *subcoder,
static inline void
-literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
+literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position)
{
// Locate the literal byte to be encoded and the subcoder.
const uint8_t cur_byte = mf->buffer[
@@ -80,19 +77,16 @@ literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
static void
length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state)
{
- uint32_t a0, a1, b0, b1;
- uint32_t *prices;
- uint32_t i;
-
const uint32_t table_size = lc->table_size;
lc->counters[pos_state] = table_size;
- a0 = rc_bit_0_price(lc->choice);
- a1 = rc_bit_1_price(lc->choice);
- b0 = a1 + rc_bit_0_price(lc->choice2);
- b1 = a1 + rc_bit_1_price(lc->choice2);
- prices = lc->prices[pos_state];
+ const uint32_t a0 = rc_bit_0_price(lc->choice);
+ const uint32_t a1 = rc_bit_1_price(lc->choice);
+ const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2);
+ const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2);
+ uint32_t *const prices = lc->prices[pos_state];
+ uint32_t i;
for (i = 0; i < table_size && i < LEN_LOW_SYMBOLS; ++i)
prices[i] = a0 + rc_bittree_price(lc->low[pos_state],
LEN_LOW_BITS, i);
@@ -146,39 +140,36 @@ length(lzma_range_encoder *rc, lzma_length_encoder *lc,
///////////
static inline void
-match(lzma_coder *coder, const uint32_t pos_state,
+match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
const uint32_t distance, const uint32_t len)
{
- uint32_t pos_slot;
- uint32_t len_to_pos_state;
-
update_match(coder->state);
length(&coder->rc, &coder->match_len_encoder, pos_state, len,
coder->fast_mode);
- pos_slot = get_pos_slot(distance);
- len_to_pos_state = get_len_to_pos_state(len);
- rc_bittree(&coder->rc, coder->pos_slot[len_to_pos_state],
- POS_SLOT_BITS, pos_slot);
+ const uint32_t dist_slot = get_dist_slot(distance);
+ const uint32_t dist_state = get_dist_state(len);
+ rc_bittree(&coder->rc, coder->dist_slot[dist_state],
+ DIST_SLOT_BITS, dist_slot);
- if (pos_slot >= START_POS_MODEL_INDEX) {
- const uint32_t footer_bits = (pos_slot >> 1) - 1;
- const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
- const uint32_t pos_reduced = distance - base;
+ if (dist_slot >= DIST_MODEL_START) {
+ const uint32_t footer_bits = (dist_slot >> 1) - 1;
+ const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
+ const uint32_t dist_reduced = distance - base;
- if (pos_slot < END_POS_MODEL_INDEX) {
- // Careful here: base - pos_slot - 1 can be -1, but
+ if (dist_slot < DIST_MODEL_END) {
+ // Careful here: base - dist_slot - 1 can be -1, but
// rc_bittree_reverse starts at probs[1], not probs[0].
rc_bittree_reverse(&coder->rc,
- coder->pos_special + base - pos_slot - 1,
- footer_bits, pos_reduced);
+ coder->dist_special + base - dist_slot - 1,
+ footer_bits, dist_reduced);
} else {
- rc_direct(&coder->rc, pos_reduced >> ALIGN_BITS,
+ rc_direct(&coder->rc, dist_reduced >> ALIGN_BITS,
footer_bits - ALIGN_BITS);
rc_bittree_reverse(
- &coder->rc, coder->pos_align,
- ALIGN_BITS, pos_reduced & ALIGN_MASK);
+ &coder->rc, coder->dist_align,
+ ALIGN_BITS, dist_reduced & ALIGN_MASK);
++coder->align_price_count;
}
}
@@ -196,7 +187,7 @@ match(lzma_coder *coder, const uint32_t pos_state,
////////////////////
static inline void
-rep_match(lzma_coder *coder, const uint32_t pos_state,
+rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
const uint32_t rep, const uint32_t len)
{
if (rep == 0) {
@@ -240,7 +231,7 @@ rep_match(lzma_coder *coder, const uint32_t pos_state,
//////////
static void
-encode_symbol(lzma_coder *coder, lzma_mf *mf,
+encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf,
uint32_t back, uint32_t len, uint32_t position)
{
const uint32_t pos_state = position & coder->pos_mask;
@@ -256,7 +247,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
rc_bit(&coder->rc,
&coder->is_match[coder->state][pos_state], 1);
- if (back < REP_DISTANCES) {
+ if (back < REPS) {
// It's a repeated match i.e. the same distance
// has been used earlier.
rc_bit(&coder->rc, &coder->is_rep[coder->state], 1);
@@ -264,7 +255,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
} else {
// Normal match
rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
- match(coder, pos_state, back - REP_DISTANCES, len);
+ match(coder, pos_state, back - REPS, len);
}
}
@@ -274,7 +265,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
static bool
-encode_init(lzma_coder *coder, lzma_mf *mf)
+encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf)
{
assert(mf_position(mf) == 0);
@@ -302,7 +293,7 @@ encode_init(lzma_coder *coder, lzma_mf *mf)
static void
-encode_eopm(lzma_coder *coder, uint32_t position)
+encode_eopm(lzma_lzma1_encoder *coder, uint32_t position)
{
const uint32_t pos_state = position & coder->pos_mask;
rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1);
@@ -318,23 +309,18 @@ encode_eopm(lzma_coder *coder, uint32_t position)
extern lzma_ret
-lzma_lzma_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size, uint32_t limit)
{
- uint32_t position;
-
// Initialize the stream if no data has been encoded yet.
if (!coder->is_initialized && !encode_init(coder, mf))
return LZMA_OK;
// Get the lowest bits of the uncompressed offset from the LZ layer.
- position = mf_position(mf);
+ uint32_t position = mf_position(mf);
while (true) {
- uint32_t len;
- uint32_t back;
-
// Encode pending bits, if any. Calling this before encoding
// the next symbol is needed only with plain LZMA, since
// LZMA2 always provides big enough buffer to flush
@@ -367,12 +353,14 @@ lzma_lzma_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
// Get optimal match (repeat position and length).
// Value ranges for pos:
- // - [0, REP_DISTANCES): repeated match
- // - [REP_DISTANCES, UINT32_MAX):
- // match at (pos - REP_DISTANCES)
+ // - [0, REPS): repeated match
+ // - [REPS, UINT32_MAX):
+ // match at (pos - REPS)
// - UINT32_MAX: not a match but a literal
// Value ranges for len:
// - [MATCH_LEN_MIN, MATCH_LEN_MAX]
+ uint32_t len;
+ uint32_t back;
if (coder->fast_mode)
lzma_lzma_optimum_fast(coder, mf, &back, &len);
@@ -414,8 +402,8 @@ lzma_lzma_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
static lzma_ret
-lzma_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+lzma_encode(void *coder, lzma_mf *restrict mf,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size)
{
// Plain LZMA has no support for sync-flushing.
@@ -465,12 +453,10 @@ static void
length_encoder_reset(lzma_length_encoder *lencoder,
const uint32_t num_pos_states, const bool fast_mode)
{
- size_t pos_state;
-
bit_reset(lencoder->choice);
bit_reset(lencoder->choice2);
- for (pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+ for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS);
bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS);
}
@@ -478,7 +464,7 @@ length_encoder_reset(lzma_length_encoder *lencoder,
bittree_reset(lencoder->high, LEN_HIGH_BITS);
if (!fast_mode)
- for (pos_state = 0; pos_state < num_pos_states;
+ for (uint32_t pos_state = 0; pos_state < num_pos_states;
++pos_state)
length_update_prices(lencoder, pos_state);
@@ -487,10 +473,9 @@ length_encoder_reset(lzma_length_encoder *lencoder,
extern lzma_ret
-lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
+lzma_lzma_encoder_reset(lzma_lzma1_encoder *coder,
+ const lzma_options_lzma *options)
{
- size_t i, j;
-
if (!is_options_valid(options))
return LZMA_OPTIONS_ERROR;
@@ -503,14 +488,14 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
// State
coder->state = STATE_LIT_LIT;
- for (i = 0; i < REP_DISTANCES; ++i)
+ for (size_t i = 0; i < REPS; ++i)
coder->reps[i] = 0;
literal_init(coder->literal, options->lc, options->lp);
// Bit encoders
- for (i = 0; i < STATES; ++i) {
- for (j = 0; j <= coder->pos_mask; ++j) {
+ for (size_t i = 0; i < STATES; ++i) {
+ for (size_t j = 0; j <= coder->pos_mask; ++j) {
bit_reset(coder->is_match[i][j]);
bit_reset(coder->is_rep0_long[i][j]);
}
@@ -521,14 +506,14 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
bit_reset(coder->is_rep2[i]);
}
- for (i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
- bit_reset(coder->pos_special[i]);
+ for (size_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
+ bit_reset(coder->dist_special[i]);
// Bit tree encoders
- for (i = 0; i < LEN_TO_POS_STATES; ++i)
- bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
+ for (size_t i = 0; i < DIST_STATES; ++i)
+ bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
- bittree_reset(coder->pos_align, ALIGN_BITS);
+ bittree_reset(coder->dist_align, ALIGN_BITS);
// Length encoders
length_encoder_reset(&coder->match_len_encoder,
@@ -561,20 +546,18 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
extern lzma_ret
-lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
+lzma_lzma_encoder_create(void **coder_ptr,
+ const lzma_allocator *allocator,
const lzma_options_lzma *options, lzma_lz_options *lz_options)
{
- lzma_coder *coder;
- uint32_t log_size = 0;
-
- // Allocate lzma_coder if it wasn't already allocated.
+ // Allocate lzma_lzma1_encoder if it wasn't already allocated.
if (*coder_ptr == NULL) {
- *coder_ptr = lzma_alloc(sizeof(lzma_coder), allocator);
+ *coder_ptr = lzma_alloc(sizeof(lzma_lzma1_encoder), allocator);
if (*coder_ptr == NULL)
return LZMA_MEM_ERROR;
}
- coder = *coder_ptr;
+ lzma_lzma1_encoder *coder = *coder_ptr;
// Set compression mode. We haven't validates the options yet,
// but it's OK here, since nothing bad happens with invalid
@@ -590,6 +573,7 @@ lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
// Set dist_table_size.
// Round the dictionary size up to next 2^n.
+ uint32_t log_size = 0;
while ((UINT32_C(1) << log_size) < options->dict_size)
++log_size;
@@ -622,7 +606,7 @@ lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
static lzma_ret
-lzma_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
+lzma_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
const void *options, lzma_lz_options *lz_options)
{
lz->code = &lzma_encode;
@@ -632,7 +616,7 @@ lzma_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
extern lzma_ret
-lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return lzma_lz_encoder_init(
@@ -643,19 +627,17 @@ lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern uint64_t
lzma_lzma_encoder_memusage(const void *options)
{
- lzma_lz_options lz_options;
- uint64_t lz_memusage;
-
if (!is_options_valid(options))
return UINT64_MAX;
+ lzma_lz_options lz_options;
set_lz_options(&lz_options, options);
- lz_memusage = lzma_lz_encoder_memusage(&lz_options);
+ const uint64_t lz_memusage = lzma_lz_encoder_memusage(&lz_options);
if (lz_memusage == UINT64_MAX)
return UINT64_MAX;
- return (uint64_t)(sizeof(lzma_coder)) + lz_memusage;
+ return (uint64_t)(sizeof(lzma_lzma1_encoder)) + lz_memusage;
}
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.h b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.h
index abb8d8b46..6cfdf228b 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.h
@@ -17,8 +17,12 @@
#include "common.h"
+typedef struct lzma_lzma1_encoder_s lzma_lzma1_encoder;
+
+
extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern uint64_t lzma_lzma_encoder_memusage(const void *options);
@@ -35,18 +39,18 @@ extern bool lzma_lzma_lclppb_encode(
/// Initializes raw LZMA encoder; this is used by LZMA2.
extern lzma_ret lzma_lzma_encoder_create(
- lzma_coder **coder_ptr, lzma_allocator *allocator,
+ void **coder_ptr, const lzma_allocator *allocator,
const lzma_options_lzma *options, lzma_lz_options *lz_options);
/// Resets an already initialized LZMA encoder; this is used by LZMA2.
extern lzma_ret lzma_lzma_encoder_reset(
- lzma_coder *coder, const lzma_options_lzma *options);
+ lzma_lzma1_encoder *coder, const lzma_options_lzma *options);
-extern lzma_ret lzma_lzma_encode(lzma_coder *LZMA_RESTRICT coder,
- lzma_mf *LZMA_RESTRICT mf, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+extern lzma_ret lzma_lzma_encode(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
uint32_t read_limit);
#endif
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c
index f98312643..6c53d2bd0 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_fast.c
@@ -10,6 +10,7 @@
///////////////////////////////////////////////////////////////////////////////
#include "lzma_encoder_private.h"
+#include "memcmplen.h"
#define change_pair(small_dist, big_dist) \
@@ -17,17 +18,10 @@
extern void
-lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res)
+lzma_lzma_optimum_fast(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res)
{
- const uint8_t *buf;
- uint32_t buf_avail;
- uint32_t i;
- uint32_t rep_len = 0;
- uint32_t rep_index = 0;
- uint32_t back_main = 0;
- uint32_t limit;
-
const uint32_t nice_len = mf->nice_len;
uint32_t len_main;
@@ -40,8 +34,8 @@ lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT m
matches_count = coder->matches_count;
}
- buf = mf_ptr(mf) - 1;
- buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
+ const uint8_t *buf = mf_ptr(mf) - 1;
+ const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
if (buf_avail < 2) {
// There's not enough input left to encode a match.
@@ -51,9 +45,10 @@ lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT m
}
// Look for repeated matches; scan the previous four match distances
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len;
+ uint32_t rep_len = 0;
+ uint32_t rep_index = 0;
+ for (uint32_t i = 0; i < REPS; ++i) {
// Pointer to the beginning of the match candidate
const uint8_t *const buf_back = buf - coder->reps[i] - 1;
@@ -64,8 +59,8 @@ lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT m
// The first two bytes matched.
// Calculate the length of the match.
- for (len = 2; len < buf_avail
- && buf[len] == buf_back[len]; ++len) ;
+ const uint32_t len = lzma_memcmplen(
+ buf, buf_back, 2, buf_avail);
// If we have found a repeated match that is at least
// nice_len long, return it immediately.
@@ -85,13 +80,13 @@ lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT m
// We didn't find a long enough repeated match. Encode it as a normal
// match if the match length is at least nice_len.
if (len_main >= nice_len) {
- *back_res = coder->matches[matches_count - 1].dist
- + REP_DISTANCES;
+ *back_res = coder->matches[matches_count - 1].dist + REPS;
*len_res = len_main;
mf_skip(mf, len_main - 1);
return;
}
+ uint32_t back_main = 0;
if (len_main >= 2) {
back_main = coder->matches[matches_count - 1].dist;
@@ -158,27 +153,17 @@ lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT m
// the old buf pointer instead of recalculating it with mf_ptr().
++buf;
- limit = len_main - 1;
-
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len;
-
- const uint8_t *const buf_back = buf - coder->reps[i] - 1;
-
- if (not_equal_16(buf, buf_back))
- continue;
-
- for (len = 2; len < limit
- && buf[len] == buf_back[len]; ++len) ;
+ const uint32_t limit = my_max(2, len_main - 1);
- if (len >= limit) {
+ for (uint32_t i = 0; i < REPS; ++i) {
+ if (memcmp(buf, buf - coder->reps[i] - 1, limit) == 0) {
*back_res = UINT32_MAX;
*len_res = 1;
return;
}
}
- *back_res = back_main + REP_DISTANCES;
+ *back_res = back_main + REPS;
*len_res = len_main;
mf_skip(mf, len_main - 2);
return;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
index d3a63485c..59f77343e 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
@@ -11,6 +11,7 @@
#include "lzma_encoder_private.h"
#include "fastpos.h"
+#include "memcmplen.h"
////////////
@@ -18,7 +19,7 @@
////////////
static uint32_t
-get_literal_price(const lzma_coder *const coder, const uint32_t pos,
+get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos,
const uint32_t prev_byte, const bool match_mode,
uint32_t match_byte, uint32_t symbol)
{
@@ -35,15 +36,12 @@ get_literal_price(const lzma_coder *const coder, const uint32_t pos,
symbol += UINT32_C(1) << 8;
do {
- uint32_t match_bit;
- uint32_t subcoder_index;
- uint32_t bit;
-
match_byte <<= 1;
- match_bit = match_byte & offset;
- subcoder_index = offset + match_bit + (symbol >> 8);
- bit = (symbol >> 7) & 1;
+ const uint32_t match_bit = match_byte & offset;
+ const uint32_t subcoder_index
+ = offset + match_bit + (symbol >> 8);
+ const uint32_t bit = (symbol >> 7) & 1;
price += rc_bit_price(subcoder[subcoder_index], bit);
symbol <<= 1;
@@ -67,7 +65,7 @@ get_len_price(const lzma_length_encoder *const lencoder,
static inline uint32_t
-get_short_rep_price(const lzma_coder *const coder,
+get_short_rep_price(const lzma_lzma1_encoder *const coder,
const lzma_lzma_state state, const uint32_t pos_state)
{
return rc_bit_0_price(coder->is_rep0[state])
@@ -76,7 +74,7 @@ get_short_rep_price(const lzma_coder *const coder,
static inline uint32_t
-get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
const lzma_lzma_state state, uint32_t pos_state)
{
uint32_t price;
@@ -101,7 +99,7 @@ get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
static inline uint32_t
-get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
const uint32_t len, const lzma_lzma_state state,
const uint32_t pos_state)
{
@@ -111,18 +109,18 @@ get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
static inline uint32_t
-get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
+get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist,
const uint32_t len, const uint32_t pos_state)
{
- const uint32_t len_to_pos_state = get_len_to_pos_state(len);
+ const uint32_t dist_state = get_dist_state(len);
uint32_t price;
- if (pos < FULL_DISTANCES) {
- price = coder->distances_prices[len_to_pos_state][pos];
+ if (dist < FULL_DISTANCES) {
+ price = coder->dist_prices[dist_state][dist];
} else {
- const uint32_t pos_slot = get_pos_slot_2(pos);
- price = coder->pos_slot_prices[len_to_pos_state][pos_slot]
- + coder->align_prices[pos & ALIGN_MASK];
+ const uint32_t dist_slot = get_dist_slot_2(dist);
+ price = coder->dist_slot_prices[dist_state][dist_slot]
+ + coder->align_prices[dist & ALIGN_MASK];
}
price += get_len_price(&coder->match_len_encoder, len, pos_state);
@@ -132,59 +130,53 @@ get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
static void
-fill_distances_prices(lzma_coder *coder)
+fill_dist_prices(lzma_lzma1_encoder *coder)
{
- uint32_t len_to_pos_state;
- uint32_t pos_slot;
- uint32_t i;
-
- for (len_to_pos_state = 0;
- len_to_pos_state < LEN_TO_POS_STATES;
- ++len_to_pos_state) {
+ for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {
- uint32_t *const pos_slot_prices
- = coder->pos_slot_prices[len_to_pos_state];
+ uint32_t *const dist_slot_prices
+ = coder->dist_slot_prices[dist_state];
- // Price to encode the pos_slot.
- for (pos_slot = 0;
- pos_slot < coder->dist_table_size; ++pos_slot)
- pos_slot_prices[pos_slot] = rc_bittree_price(
- coder->pos_slot[len_to_pos_state],
- POS_SLOT_BITS, pos_slot);
+ // Price to encode the dist_slot.
+ for (uint32_t dist_slot = 0;
+ dist_slot < coder->dist_table_size; ++dist_slot)
+ dist_slot_prices[dist_slot] = rc_bittree_price(
+ coder->dist_slot[dist_state],
+ DIST_SLOT_BITS, dist_slot);
// For matches with distance >= FULL_DISTANCES, add the price
// of the direct bits part of the match distance. (Align bits
// are handled by fill_align_prices()).
- for (pos_slot = END_POS_MODEL_INDEX;
- pos_slot < coder->dist_table_size; ++pos_slot)
- pos_slot_prices[pos_slot] += rc_direct_price(
- ((pos_slot >> 1) - 1) - ALIGN_BITS);
+ for (uint32_t dist_slot = DIST_MODEL_END;
+ dist_slot < coder->dist_table_size;
+ ++dist_slot)
+ dist_slot_prices[dist_slot] += rc_direct_price(
+ ((dist_slot >> 1) - 1) - ALIGN_BITS);
// Distances in the range [0, 3] are fully encoded with
- // pos_slot, so they are used for coder->distances_prices
+ // dist_slot, so they are used for coder->dist_prices
// as is.
- for (i = 0; i < START_POS_MODEL_INDEX; ++i)
- coder->distances_prices[len_to_pos_state][i]
- = pos_slot_prices[i];
+ for (uint32_t i = 0; i < DIST_MODEL_START; ++i)
+ coder->dist_prices[dist_state][i]
+ = dist_slot_prices[i];
}
- // Distances in the range [4, 127] depend on pos_slot and pos_special.
- // We do this in a loop separate from the above loop to avoid
- // redundant calls to get_pos_slot().
- for (i = START_POS_MODEL_INDEX; i < FULL_DISTANCES; ++i) {
- const uint32_t pos_slot = get_pos_slot(i);
- const uint32_t footer_bits = ((pos_slot >> 1) - 1);
- const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
+ // Distances in the range [4, 127] depend on dist_slot and
+ // dist_special. We do this in a loop separate from the above
+ // loop to avoid redundant calls to get_dist_slot().
+ for (uint32_t i = DIST_MODEL_START; i < FULL_DISTANCES; ++i) {
+ const uint32_t dist_slot = get_dist_slot(i);
+ const uint32_t footer_bits = ((dist_slot >> 1) - 1);
+ const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
const uint32_t price = rc_bittree_reverse_price(
- coder->pos_special + base - pos_slot - 1,
+ coder->dist_special + base - dist_slot - 1,
footer_bits, i - base);
- for (len_to_pos_state = 0;
- len_to_pos_state < LEN_TO_POS_STATES;
- ++len_to_pos_state)
- coder->distances_prices[len_to_pos_state][i]
- = price + coder->pos_slot_prices[
- len_to_pos_state][pos_slot];
+ for (uint32_t dist_state = 0; dist_state < DIST_STATES;
+ ++dist_state)
+ coder->dist_prices[dist_state][i]
+ = price + coder->dist_slot_prices[
+ dist_state][dist_slot];
}
coder->match_price_count = 0;
@@ -193,12 +185,11 @@ fill_distances_prices(lzma_coder *coder)
static void
-fill_align_prices(lzma_coder *coder)
+fill_align_prices(lzma_lzma1_encoder *coder)
{
- uint32_t i;
- for (i = 0; i < ALIGN_TABLE_SIZE; ++i)
+ for (uint32_t i = 0; i < ALIGN_SIZE; ++i)
coder->align_prices[i] = rc_bittree_reverse_price(
- coder->pos_align, ALIGN_BITS, i);
+ coder->dist_align, ALIGN_BITS, i);
coder->align_price_count = 0;
return;
@@ -230,18 +221,15 @@ make_short_rep(lzma_optimal *optimal)
static void
-backward(lzma_coder *LZMA_RESTRICT coder, uint32_t *LZMA_RESTRICT len_res,
- uint32_t *LZMA_RESTRICT back_res, uint32_t cur)
+backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res,
+ uint32_t *restrict back_res, uint32_t cur)
{
+ coder->opts_end_index = cur;
+
uint32_t pos_mem = coder->opts[cur].pos_prev;
uint32_t back_mem = coder->opts[cur].back_prev;
- coder->opts_end_index = cur;
-
do {
- const uint32_t pos_prev = pos_mem;
- const uint32_t back_cur = back_mem;
-
if (coder->opts[cur].prev_1_is_literal) {
make_literal(&coder->opts[pos_mem]);
coder->opts[pos_mem].pos_prev = pos_mem - 1;
@@ -256,6 +244,9 @@ backward(lzma_coder *LZMA_RESTRICT coder, uint32_t *LZMA_RESTRICT len_res,
}
}
+ const uint32_t pos_prev = pos_mem;
+ const uint32_t back_cur = back_mem;
+
back_mem = coder->opts[pos_prev].back_prev;
pos_mem = coder->opts[pos_prev].pos_prev;
@@ -278,27 +269,10 @@ backward(lzma_coder *LZMA_RESTRICT coder, uint32_t *LZMA_RESTRICT len_res,
//////////
static inline uint32_t
-helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res,
+helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res,
uint32_t position)
{
- uint32_t buf_avail;
- const uint8_t *buf;
- uint32_t rep_lens[REP_DISTANCES];
- uint32_t rep_max_index = 0;
- uint32_t i;
-
- uint8_t current_byte;
- uint8_t match_byte;
-
- uint32_t pos_state;
- uint32_t match_price;
- uint32_t rep_match_price;
- uint32_t len_end;
- uint32_t len;
-
- uint32_t normal_match_price;
-
const uint32_t nice_len = mf->nice_len;
uint32_t len_main;
@@ -312,18 +286,19 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
matches_count = coder->matches_count;
}
- buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
+ const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
if (buf_avail < 2) {
*back_res = UINT32_MAX;
*len_res = 1;
return UINT32_MAX;
}
- buf = mf_ptr(mf) - 1;
+ const uint8_t *const buf = mf_ptr(mf) - 1;
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len_test;
+ uint32_t rep_lens[REPS];
+ uint32_t rep_max_index = 0;
+ for (uint32_t i = 0; i < REPS; ++i) {
const uint8_t *const buf_back = buf - coder->reps[i] - 1;
if (not_equal_16(buf, buf_back)) {
@@ -331,12 +306,9 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
continue;
}
- for (len_test = 2; len_test < buf_avail
- && buf[len_test] == buf_back[len_test];
- ++len_test) ;
+ rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail);
- rep_lens[i] = len_test;
- if (len_test > rep_lens[rep_max_index])
+ if (rep_lens[i] > rep_lens[rep_max_index])
rep_max_index = i;
}
@@ -349,15 +321,14 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
if (len_main >= nice_len) {
- *back_res = coder->matches[matches_count - 1].dist
- + REP_DISTANCES;
+ *back_res = coder->matches[matches_count - 1].dist + REPS;
*len_res = len_main;
mf_skip(mf, len_main - 1);
return UINT32_MAX;
}
- current_byte = *buf;
- match_byte = *(buf - coder->reps[0] - 1);
+ const uint8_t current_byte = *buf;
+ const uint8_t match_byte = *(buf - coder->reps[0] - 1);
if (len_main < 2 && current_byte != match_byte
&& rep_lens[rep_max_index] < 2) {
@@ -368,7 +339,7 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
coder->opts[0].state = coder->state;
- pos_state = position & coder->pos_mask;
+ const uint32_t pos_state = position & coder->pos_mask;
coder->opts[1].price = rc_bit_0_price(
coder->is_match[coder->state][pos_state])
@@ -378,9 +349,9 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
make_literal(&coder->opts[1]);
- match_price = rc_bit_1_price(
+ const uint32_t match_price = rc_bit_1_price(
coder->is_match[coder->state][pos_state]);
- rep_match_price = match_price
+ const uint32_t rep_match_price = match_price
+ rc_bit_1_price(coder->is_rep[coder->state]);
if (match_byte == current_byte) {
@@ -394,7 +365,7 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
}
}
- len_end = my_max(len_main, rep_lens[rep_max_index]);
+ const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]);
if (len_end < 2) {
*back_res = coder->opts[1].back_prev;
@@ -404,23 +375,21 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
coder->opts[1].pos_prev = 0;
- for (i = 0; i < REP_DISTANCES; ++i)
+ for (uint32_t i = 0; i < REPS; ++i)
coder->opts[0].backs[i] = coder->reps[i];
- len = len_end;
+ uint32_t len = len_end;
do {
coder->opts[len].price = RC_INFINITY_PRICE;
} while (--len >= 2);
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t price;
-
+ for (uint32_t i = 0; i < REPS; ++i) {
uint32_t rep_len = rep_lens[i];
if (rep_len < 2)
continue;
- price = rep_match_price + get_pure_rep_price(
+ const uint32_t price = rep_match_price + get_pure_rep_price(
coder, i, coder->state, pos_state);
do {
@@ -439,7 +408,7 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
}
- normal_match_price = match_price
+ const uint32_t normal_match_price = match_price
+ rc_bit_0_price(coder->is_rep[coder->state]);
len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;
@@ -451,14 +420,13 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
for(; ; ++len) {
const uint32_t dist = coder->matches[i].dist;
const uint32_t cur_and_len_price = normal_match_price
- + get_pos_len_price(coder,
+ + get_dist_len_price(coder,
dist, len, pos_state);
if (cur_and_len_price < coder->opts[len].price) {
coder->opts[len].price = cur_and_len_price;
coder->opts[len].pos_prev = 0;
- coder->opts[len].back_prev
- = dist + REP_DISTANCES;
+ coder->opts[len].back_prev = dist + REPS;
coder->opts[len].prev_1_is_literal = false;
}
@@ -473,7 +441,7 @@ helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
static inline uint32_t
-helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
+helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,
uint32_t len_end, uint32_t position, const uint32_t cur,
const uint32_t nice_len, const uint32_t buf_avail_full)
{
@@ -481,19 +449,6 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
uint32_t new_len = coder->longest_match_length;
uint32_t pos_prev = coder->opts[cur].pos_prev;
lzma_lzma_state state;
- uint32_t buf_avail;
- uint32_t rep_index;
- uint32_t i;
-
- uint32_t cur_price;
- uint8_t current_byte;
- uint8_t match_byte;
- uint32_t pos_state;
- uint32_t cur_and_1_price;
- bool next_is_literal = false;
- uint32_t match_price;
- uint32_t rep_match_price;
- uint32_t start_len = 2;
if (coder->opts[cur].prev_1_is_literal) {
--pos_prev;
@@ -501,7 +456,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
if (coder->opts[cur].prev_2) {
state = coder->opts[coder->opts[cur].pos_prev_2].state;
- if (coder->opts[cur].back_prev_2 < REP_DISTANCES)
+ if (coder->opts[cur].back_prev_2 < REPS)
update_long_rep(state);
else
update_match(state);
@@ -530,48 +485,49 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
update_long_rep(state);
} else {
pos = coder->opts[cur].back_prev;
- if (pos < REP_DISTANCES)
+ if (pos < REPS)
update_long_rep(state);
else
update_match(state);
}
- if (pos < REP_DISTANCES) {
- uint32_t i;
-
+ if (pos < REPS) {
reps[0] = coder->opts[pos_prev].backs[pos];
+ uint32_t i;
for (i = 1; i <= pos; ++i)
reps[i] = coder->opts[pos_prev].backs[i - 1];
- for (; i < REP_DISTANCES; ++i)
+ for (; i < REPS; ++i)
reps[i] = coder->opts[pos_prev].backs[i];
} else {
- reps[0] = pos - REP_DISTANCES;
+ reps[0] = pos - REPS;
- for (i = 1; i < REP_DISTANCES; ++i)
+ for (uint32_t i = 1; i < REPS; ++i)
reps[i] = coder->opts[pos_prev].backs[i - 1];
}
}
coder->opts[cur].state = state;
- for (i = 0; i < REP_DISTANCES; ++i)
+ for (uint32_t i = 0; i < REPS; ++i)
coder->opts[cur].backs[i] = reps[i];
- cur_price = coder->opts[cur].price;
+ const uint32_t cur_price = coder->opts[cur].price;
- current_byte = *buf;
- match_byte = *(buf - reps[0] - 1);
+ const uint8_t current_byte = *buf;
+ const uint8_t match_byte = *(buf - reps[0] - 1);
- pos_state = position & coder->pos_mask;
+ const uint32_t pos_state = position & coder->pos_mask;
- cur_and_1_price = cur_price
+ const uint32_t cur_and_1_price = cur_price
+ rc_bit_0_price(coder->is_match[state][pos_state])
+ get_literal_price(coder, position, buf[-1],
!is_literal_state(state), match_byte, current_byte);
+ bool next_is_literal = false;
+
if (cur_and_1_price < coder->opts[cur + 1].price) {
coder->opts[cur + 1].price = cur_and_1_price;
coder->opts[cur + 1].pos_prev = cur;
@@ -579,9 +535,9 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
next_is_literal = true;
}
- match_price = cur_price
+ const uint32_t match_price = cur_price
+ rc_bit_1_price(coder->is_match[state][pos_state]);
- rep_match_price = match_price
+ const uint32_t rep_match_price = match_price
+ rc_bit_1_price(coder->is_rep[state]);
if (match_byte == current_byte
@@ -602,40 +558,31 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
if (buf_avail_full < 2)
return len_end;
- buf_avail = my_min(buf_avail_full, nice_len);
+ const uint32_t buf_avail = my_min(buf_avail_full, nice_len);
if (!next_is_literal && match_byte != current_byte) { // speed optimization
// try literal + rep0
const uint8_t *const buf_back = buf - reps[0] - 1;
const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
- uint32_t len_test = 1;
- while (len_test < limit && buf[len_test] == buf_back[len_test])
- ++len_test;
-
- --len_test;
+ const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1;
if (len_test >= 2) {
- uint32_t pos_state_next;
- uint32_t next_rep_match_price;
- uint32_t offset;
- uint32_t cur_and_len_price;
-
lzma_lzma_state state_2 = state;
update_literal(state_2);
- pos_state_next = (position + 1) & coder->pos_mask;
- next_rep_match_price = cur_and_1_price
+ const uint32_t pos_state_next = (position + 1) & coder->pos_mask;
+ const uint32_t next_rep_match_price = cur_and_1_price
+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+ rc_bit_1_price(coder->is_rep[state_2]);
//for (; len_test >= 2; --len_test) {
- offset = cur + 1 + len_test;
+ const uint32_t offset = cur + 1 + len_test;
while (len_end < offset)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
+ const uint32_t cur_and_len_price = next_rep_match_price
+ get_rep_price(coder, 0, len_test,
state_2, pos_state_next);
@@ -651,23 +598,20 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
}
- for (rep_index = 0; rep_index < REP_DISTANCES; ++rep_index) {
- uint32_t len_test, len_test_2, len_test_temp;
- uint32_t price, limit;
+ uint32_t start_len = 2; // speed optimization
+ for (uint32_t rep_index = 0; rep_index < REPS; ++rep_index) {
const uint8_t *const buf_back = buf - reps[rep_index] - 1;
if (not_equal_16(buf, buf_back))
continue;
- for (len_test = 2; len_test < buf_avail
- && buf[len_test] == buf_back[len_test];
- ++len_test) ;
+ uint32_t len_test = lzma_memcmplen(buf, buf_back, 2, buf_avail);
while (len_end < cur + len_test)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
- len_test_temp = len_test;
- price = rep_match_price + get_pure_rep_price(
+ const uint32_t len_test_temp = len_test;
+ const uint32_t price = rep_match_price + get_pure_rep_price(
coder, rep_index, state, pos_state);
do {
@@ -689,8 +633,8 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
start_len = len_test + 1;
- len_test_2 = len_test + 1;
- limit = my_min(buf_avail_full,
+ uint32_t len_test_2 = len_test + 1;
+ const uint32_t limit = my_min(buf_avail_full,
len_test_2 + nice_len);
for (; len_test_2 < limit
&& buf[len_test_2] == buf_back[len_test_2];
@@ -699,18 +643,12 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
len_test_2 -= len_test + 1;
if (len_test_2 >= 2) {
- uint32_t pos_state_next;
- uint32_t cur_and_len_literal_price;
- uint32_t next_rep_match_price;
- uint32_t offset;
- uint32_t cur_and_len_price;
-
lzma_lzma_state state_2 = state;
update_long_rep(state_2);
- pos_state_next = (position + len_test) & coder->pos_mask;
+ uint32_t pos_state_next = (position + len_test) & coder->pos_mask;
- cur_and_len_literal_price = price
+ const uint32_t cur_and_len_literal_price = price
+ get_len_price(&coder->rep_len_encoder,
len_test, pos_state)
+ rc_bit_0_price(coder->is_match[state_2][pos_state_next])
@@ -722,17 +660,17 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
pos_state_next = (position + len_test + 1) & coder->pos_mask;
- next_rep_match_price = cur_and_len_literal_price
+ const uint32_t next_rep_match_price = cur_and_len_literal_price
+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+ rc_bit_1_price(coder->is_rep[state_2]);
//for(; len_test_2 >= 2; len_test_2--) {
- offset = cur + len_test + 1 + len_test_2;
+ const uint32_t offset = cur + len_test + 1 + len_test_2;
while (len_end < offset)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
+ const uint32_t cur_and_len_price = next_rep_match_price
+ get_rep_price(coder, 0, len_test_2,
state_2, pos_state_next);
@@ -763,29 +701,27 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
if (new_len >= start_len) {
- uint32_t len_test;
- uint32_t i = 0;
-
const uint32_t normal_match_price = match_price
+ rc_bit_0_price(coder->is_rep[state]);
while (len_end < cur + new_len)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
+ uint32_t i = 0;
while (start_len > coder->matches[i].len)
++i;
- for (len_test = start_len; ; ++len_test) {
+ for (uint32_t len_test = start_len; ; ++len_test) {
const uint32_t cur_back = coder->matches[i].dist;
uint32_t cur_and_len_price = normal_match_price
- + get_pos_len_price(coder,
+ + get_dist_len_price(coder,
cur_back, len_test, pos_state);
if (cur_and_len_price < coder->opts[cur + len_test].price) {
coder->opts[cur + len_test].price = cur_and_len_price;
coder->opts[cur + len_test].pos_prev = cur;
coder->opts[cur + len_test].back_prev
- = cur_back + REP_DISTANCES;
+ = cur_back + REPS;
coder->opts[cur + len_test].prev_1_is_literal = false;
}
@@ -803,16 +739,12 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
len_test_2 -= len_test + 1;
if (len_test_2 >= 2) {
- uint32_t pos_state_next;
- uint32_t cur_and_len_literal_price;
- uint32_t next_rep_match_price;
- uint32_t offset;
-
lzma_lzma_state state_2 = state;
update_match(state_2);
- pos_state_next = (position + len_test) & coder->pos_mask;
+ uint32_t pos_state_next
+ = (position + len_test) & coder->pos_mask;
- cur_and_len_literal_price = cur_and_len_price
+ const uint32_t cur_and_len_literal_price = cur_and_len_price
+ rc_bit_0_price(
coder->is_match[state_2][pos_state_next])
+ get_literal_price(coder,
@@ -825,14 +757,14 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
update_literal(state_2);
pos_state_next = (pos_state_next + 1) & coder->pos_mask;
- next_rep_match_price
+ const uint32_t next_rep_match_price
= cur_and_len_literal_price
+ rc_bit_1_price(
coder->is_match[state_2][pos_state_next])
+ rc_bit_1_price(coder->is_rep[state_2]);
// for(; len_test_2 >= 2; --len_test_2) {
- offset = cur + len_test + 1 + len_test_2;
+ const uint32_t offset = cur + len_test + 1 + len_test_2;
while (len_end < offset)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
@@ -849,7 +781,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
coder->opts[offset].prev_2 = true;
coder->opts[offset].pos_prev_2 = cur;
coder->opts[offset].back_prev_2
- = cur_back + REP_DISTANCES;
+ = cur_back + REPS;
}
//}
}
@@ -865,14 +797,11 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
extern void
-lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res,
+lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res,
uint32_t position)
{
- uint32_t reps[REP_DISTANCES];
- uint32_t len_end;
- uint32_t cur;
-
// If we have symbols pending, return the next pending symbol.
if (coder->opts_end_index != coder->opts_current_index) {
assert(mf->read_ahead > 0);
@@ -889,9 +818,9 @@ lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT
// In liblzma they were moved into this single place.
if (mf->read_ahead == 0) {
if (coder->match_price_count >= (1 << 7))
- fill_distances_prices(coder);
+ fill_dist_prices(coder);
- if (coder->align_price_count >= ALIGN_TABLE_SIZE)
+ if (coder->align_price_count >= ALIGN_SIZE)
fill_align_prices(coder);
}
@@ -899,13 +828,14 @@ lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT
// the original function into two pieces makes it at least a little
// more readable, since those two parts don't share many variables.
- len_end = helper1(coder, mf, back_res, len_res, position);
+ uint32_t len_end = helper1(coder, mf, back_res, len_res, position);
if (len_end == UINT32_MAX)
return;
-
+ uint32_t reps[REPS];
memcpy(reps, coder->reps, sizeof(reps));
+ uint32_t cur;
for (cur = 1; cur < len_end; ++cur) {
assert(cur < OPTS);
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_presets.c b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_presets.c
index 9332abfa5..711df0255 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_presets.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_presets.c
@@ -2,6 +2,7 @@
//
/// \file lzma_encoder_presets.c
/// \brief Encoder presets
+/// \note xz needs this even when only decoding is enabled.
//
// Author: Lasse Collin
//
@@ -16,10 +17,6 @@
extern LZMA_API(lzma_bool)
lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
{
- static const uint8_t dict_pow2[]
- = { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 };
- static const uint8_t depths[] = { 4, 8, 24, 48 };
-
const uint32_t level = preset & LZMA_PRESET_LEVEL_MASK;
const uint32_t flags = preset & ~LZMA_PRESET_LEVEL_MASK;
const uint32_t supported_flags = LZMA_PRESET_EXTREME;
@@ -34,12 +31,15 @@ lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
options->lp = LZMA_LP_DEFAULT;
options->pb = LZMA_PB_DEFAULT;
+ static const uint8_t dict_pow2[]
+ = { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 };
options->dict_size = UINT32_C(1) << dict_pow2[level];
if (level <= 3) {
options->mode = LZMA_MODE_FAST;
options->mf = level == 0 ? LZMA_MF_HC3 : LZMA_MF_HC4;
options->nice_len = level <= 1 ? 128 : 273;
+ static const uint8_t depths[] = { 4, 8, 24, 48 };
options->depth = depths[level];
} else {
options->mode = LZMA_MODE_NORMAL;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h
index 04fb29e90..a2da969f4 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h
@@ -64,12 +64,12 @@ typedef struct {
uint32_t pos_prev; // pos_next;
uint32_t back_prev;
- uint32_t backs[REP_DISTANCES];
+ uint32_t backs[REPS];
} lzma_optimal;
-struct lzma_coder_s {
+struct lzma_lzma1_encoder_s {
/// Range encoder
lzma_range_encoder rc;
@@ -77,7 +77,7 @@ struct lzma_coder_s {
lzma_lzma_state state;
/// The four most recent match distances
- uint32_t reps[REP_DISTANCES];
+ uint32_t reps[REPS];
/// Array of match candidates
lzma_match matches[MATCH_LEN_MAX + 1];
@@ -112,9 +112,9 @@ struct lzma_coder_s {
probability is_rep1[STATES];
probability is_rep2[STATES];
probability is_rep0_long[STATES][POS_STATES_MAX];
- probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
- probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
- probability pos_align[ALIGN_TABLE_SIZE];
+ probability dist_slot[DIST_STATES][DIST_SLOTS];
+ probability dist_special[FULL_DISTANCES - DIST_MODEL_END];
+ probability dist_align[ALIGN_SIZE];
// These are the same as in lzma_decoder.c except that the encoders
// include also price tables.
@@ -122,12 +122,12 @@ struct lzma_coder_s {
lzma_length_encoder rep_len_encoder;
// Price tables
- uint32_t pos_slot_prices[LEN_TO_POS_STATES][POS_SLOTS];
- uint32_t distances_prices[LEN_TO_POS_STATES][FULL_DISTANCES];
+ uint32_t dist_slot_prices[DIST_STATES][DIST_SLOTS];
+ uint32_t dist_prices[DIST_STATES][FULL_DISTANCES];
uint32_t dist_table_size;
uint32_t match_price_count;
- uint32_t align_prices[ALIGN_TABLE_SIZE];
+ uint32_t align_prices[ALIGN_SIZE];
uint32_t align_price_count;
// Optimal
@@ -138,11 +138,11 @@ struct lzma_coder_s {
extern void lzma_lzma_optimum_fast(
- lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res);
+ lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res);
-extern void lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder,
- lzma_mf *LZMA_RESTRICT mf, uint32_t *LZMA_RESTRICT back_res,
- uint32_t *LZMA_RESTRICT len_res, uint32_t position);
+extern void lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf, uint32_t *restrict back_res,
+ uint32_t *restrict len_res, uint32_t position);
#endif
diff --git a/Utilities/cmliblzma/liblzma/rangecoder/range_common.h b/Utilities/cmliblzma/liblzma/rangecoder/range_common.h
index f15623ea6..2c74dc153 100644
--- a/Utilities/cmliblzma/liblzma/rangecoder/range_common.h
+++ b/Utilities/cmliblzma/liblzma/rangecoder/range_common.h
@@ -40,11 +40,8 @@
// This does the same for a complete bit tree.
// (A tree represented as an array.)
#define bittree_reset(probs, bit_levels) \
- do { \
- uint32_t bt_i; \
- for (bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \
- bit_reset((probs)[bt_i]); \
- } while (0)
+ for (uint32_t bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \
+ bit_reset((probs)[bt_i])
//////////////////////
diff --git a/Utilities/cmliblzma/liblzma/rangecoder/range_decoder.h b/Utilities/cmliblzma/liblzma/rangecoder/range_decoder.h
index 199e7b5a6..e0b051fac 100644
--- a/Utilities/cmliblzma/liblzma/rangecoder/range_decoder.h
+++ b/Utilities/cmliblzma/liblzma/rangecoder/range_decoder.h
@@ -25,20 +25,26 @@ typedef struct {
/// Reads the first five bytes to initialize the range decoder.
-static inline bool
-rc_read_init(lzma_range_decoder *rc, const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size)
+static inline lzma_ret
+rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size)
{
while (rc->init_bytes_left > 0) {
if (*in_pos == in_size)
- return false;
+ return LZMA_OK;
+
+ // The first byte is always 0x00. It could have been omitted
+ // in LZMA2 but it wasn't, so one byte is wasted in every
+ // LZMA2 chunk.
+ if (rc->init_bytes_left == 5 && in[*in_pos] != 0x00)
+ return LZMA_DATA_ERROR;
rc->code = (rc->code << 8) | in[*in_pos];
++*in_pos;
--rc->init_bytes_left;
}
- return true;
+ return LZMA_STREAM_END;
}
diff --git a/Utilities/cmliblzma/liblzma/rangecoder/range_encoder.h b/Utilities/cmliblzma/liblzma/rangecoder/range_encoder.h
index e9614f252..1e1c36995 100644
--- a/Utilities/cmliblzma/liblzma/rangecoder/range_encoder.h
+++ b/Utilities/cmliblzma/liblzma/rangecoder/range_encoder.h
@@ -115,8 +115,7 @@ rc_direct(lzma_range_encoder *rc,
static inline void
rc_flush(lzma_range_encoder *rc)
{
- size_t i;
- for (i = 0; i < 5; ++i)
+ for (size_t i = 0; i < 5; ++i)
rc->symbols[rc->count++] = RC_FLUSH;
}
diff --git a/Utilities/cmliblzma/liblzma/simple/arm.c b/Utilities/cmliblzma/liblzma/simple/arm.c
index 8dcba39fd..181d0e3b2 100644
--- a/Utilities/cmliblzma/liblzma/simple/arm.c
+++ b/Utilities/cmliblzma/liblzma/simple/arm.c
@@ -15,19 +15,19 @@
static size_t
-arm_code(lzma_simple *simple lzma_attribute((__unused__)),
+arm_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
size_t i;
for (i = 0; i + 4 <= size; i += 4) {
if (buffer[i + 3] == 0xEB) {
- uint32_t dest;
uint32_t src = (buffer[i + 2] << 16)
| (buffer[i + 1] << 8)
| (buffer[i + 0]);
src <<= 2;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + 8 + src;
else
@@ -45,7 +45,7 @@ arm_code(lzma_simple *simple lzma_attribute((__unused__)),
static lzma_ret
-arm_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+arm_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
@@ -54,7 +54,8 @@ arm_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
-lzma_simple_arm_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_arm_encoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return arm_coder_init(next, allocator, filters, true);
@@ -62,7 +63,8 @@ lzma_simple_arm_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
-lzma_simple_arm_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_arm_decoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return arm_coder_init(next, allocator, filters, false);
diff --git a/Utilities/cmliblzma/liblzma/simple/armthumb.c b/Utilities/cmliblzma/liblzma/simple/armthumb.c
index 4b890a395..eab4862dd 100644
--- a/Utilities/cmliblzma/liblzma/simple/armthumb.c
+++ b/Utilities/cmliblzma/liblzma/simple/armthumb.c
@@ -15,7 +15,7 @@
static size_t
-armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
+armthumb_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
@@ -23,7 +23,6 @@ armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
for (i = 0; i + 4 <= size; i += 2) {
if ((buffer[i + 1] & 0xF8) == 0xF0
&& (buffer[i + 3] & 0xF8) == 0xF8) {
- uint32_t dest;
uint32_t src = ((buffer[i + 1] & 0x7) << 19)
| (buffer[i + 0] << 11)
| ((buffer[i + 3] & 0x7) << 8)
@@ -31,6 +30,7 @@ armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
src <<= 1;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + 4 + src;
else
@@ -50,7 +50,7 @@ armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
static lzma_ret
-armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+armthumb_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
@@ -60,7 +60,8 @@ armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return armthumb_coder_init(next, allocator, filters, true);
}
@@ -68,7 +69,8 @@ lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
extern lzma_ret
lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return armthumb_coder_init(next, allocator, filters, false);
}
diff --git a/Utilities/cmliblzma/liblzma/simple/ia64.c b/Utilities/cmliblzma/liblzma/simple/ia64.c
index c537caca1..580529e80 100644
--- a/Utilities/cmliblzma/liblzma/simple/ia64.c
+++ b/Utilities/cmliblzma/liblzma/simple/ia64.c
@@ -15,7 +15,7 @@
static size_t
-ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
+ia64_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
@@ -28,42 +28,36 @@ ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
size_t i;
for (i = 0; i + 16 <= size; i += 16) {
- size_t slot;
-
const uint32_t instr_template = buffer[i] & 0x1F;
const uint32_t mask = BRANCH_TABLE[instr_template];
uint32_t bit_pos = 5;
- for (slot = 0; slot < 3; ++slot, bit_pos += 41) {
+ for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
+ if (((mask >> slot) & 1) == 0)
+ continue;
+
const size_t byte_pos = (bit_pos >> 3);
const uint32_t bit_res = bit_pos & 0x7;
uint64_t instruction = 0;
- uint64_t inst_norm;
- size_t j;
-
- if (((mask >> slot) & 1) == 0)
- continue;
- for (j = 0; j < 6; ++j)
+ for (size_t j = 0; j < 6; ++j)
instruction += (uint64_t)(
buffer[i + j + byte_pos])
<< (8 * j);
- inst_norm = instruction >> bit_res;
+ uint64_t inst_norm = instruction >> bit_res;
if (((inst_norm >> 37) & 0xF) == 0x5
&& ((inst_norm >> 9) & 0x7) == 0
/* && (inst_norm & 0x3F)== 0 */
) {
- uint32_t dest;
- size_t j;
-
uint32_t src = (uint32_t)(
(inst_norm >> 13) & 0xFFFFF);
src |= ((inst_norm >> 36) & 1) << 20;
src <<= 4;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + src;
else
@@ -79,7 +73,7 @@ ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
instruction &= (1 << bit_res) - 1;
instruction |= (inst_norm << bit_res);
- for (j = 0; j < 6; j++)
+ for (size_t j = 0; j < 6; j++)
buffer[i + j + byte_pos] = (uint8_t)(
instruction
>> (8 * j));
@@ -92,7 +86,7 @@ ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
static lzma_ret
-ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
@@ -102,7 +96,8 @@ ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
lzma_simple_ia64_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return ia64_coder_init(next, allocator, filters, true);
}
@@ -110,7 +105,8 @@ lzma_simple_ia64_encoder_init(lzma_next_coder *next,
extern lzma_ret
lzma_simple_ia64_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return ia64_coder_init(next, allocator, filters, false);
}
diff --git a/Utilities/cmliblzma/liblzma/simple/powerpc.c b/Utilities/cmliblzma/liblzma/simple/powerpc.c
index 6f8351176..54dfbf102 100644
--- a/Utilities/cmliblzma/liblzma/simple/powerpc.c
+++ b/Utilities/cmliblzma/liblzma/simple/powerpc.c
@@ -15,7 +15,7 @@
static size_t
-powerpc_code(lzma_simple *simple lzma_attribute((__unused__)),
+powerpc_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
@@ -49,7 +49,7 @@ powerpc_code(lzma_simple *simple lzma_attribute((__unused__)),
static lzma_ret
-powerpc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+powerpc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
@@ -59,7 +59,8 @@ powerpc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return powerpc_coder_init(next, allocator, filters, true);
}
@@ -67,7 +68,8 @@ lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
extern lzma_ret
lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return powerpc_coder_init(next, allocator, filters, false);
}
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_coder.c b/Utilities/cmliblzma/liblzma/simple/simple_coder.c
index f3bbdd7a7..13ebabc76 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_coder.c
+++ b/Utilities/cmliblzma/liblzma/simple/simple_coder.c
@@ -18,10 +18,10 @@
/// Copied or encodes/decodes more data to out[].
static lzma_ret
-copy_or_code(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+copy_or_code(lzma_simple_coder *coder, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
assert(!coder->end_was_reached);
@@ -55,7 +55,7 @@ copy_or_code(lzma_coder *coder, lzma_allocator *allocator,
static size_t
-call_filter(lzma_coder *coder, uint8_t *buffer, size_t size)
+call_filter(lzma_simple_coder *coder, uint8_t *buffer, size_t size)
{
const size_t filtered = coder->filter(coder->simple,
coder->now_pos, coder->is_encoder,
@@ -66,13 +66,12 @@ call_filter(lzma_coder *coder, uint8_t *buffer, size_t size)
static lzma_ret
-simple_code(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+simple_code(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
- size_t out_avail;
- size_t buf_avail;
+ lzma_simple_coder *coder = coder_ptr;
// TODO: Add partial support for LZMA_SYNC_FLUSH. We can support it
// in cases when the filter is able to filter everything. With most
@@ -108,13 +107,9 @@ simple_code(lzma_coder *coder, lzma_allocator *allocator,
// more data to out[] hopefully filling it completely. Then filter
// the data in out[]. This step is where most of the data gets
// filtered if the buffer sizes used by the application are reasonable.
- out_avail = out_size - *out_pos;
- buf_avail = coder->size - coder->pos;
+ const size_t out_avail = out_size - *out_pos;
+ const size_t buf_avail = coder->size - coder->pos;
if (out_avail > buf_avail || buf_avail == 0) {
- size_t size;
- size_t filtered;
- size_t unfiltered;
-
// Store the old position so that we know from which byte
// to start filtering.
const size_t out_start = *out_pos;
@@ -137,10 +132,11 @@ simple_code(lzma_coder *coder, lzma_allocator *allocator,
}
// Filter out[].
- size = *out_pos - out_start;
- filtered = call_filter(coder, out + out_start, size);
+ const size_t size = *out_pos - out_start;
+ const size_t filtered = call_filter(
+ coder, out + out_start, size);
- unfiltered = size - filtered;
+ const size_t unfiltered = size - filtered;
assert(unfiltered <= coder->allocated / 2);
// Now we can update coder->pos and coder->size, because
@@ -204,8 +200,9 @@ simple_code(lzma_coder *coder, lzma_allocator *allocator,
static void
-simple_coder_end(lzma_coder *coder, lzma_allocator *allocator)
+simple_coder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_simple_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder->simple, allocator);
lzma_free(coder, allocator);
@@ -214,10 +211,12 @@ simple_coder_end(lzma_coder *coder, lzma_allocator *allocator)
static lzma_ret
-simple_coder_update(lzma_coder *coder, lzma_allocator *allocator,
+simple_coder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters_null lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_simple_coder *coder = coder_ptr;
+
// No update support, just call the next filter in the chain.
return lzma_next_filter_update(
&coder->next, allocator, reversed_filters + 1);
@@ -225,59 +224,59 @@ simple_coder_update(lzma_coder *coder, lzma_allocator *allocator,
extern lzma_ret
-lzma_simple_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
- size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+ size_t (*filter)(void *simple, uint32_t now_pos,
bool is_encoder, uint8_t *buffer, size_t size),
size_t simple_size, size_t unfiltered_max,
uint32_t alignment, bool is_encoder)
{
- // Allocate memory for the lzma_coder structure if needed.
- if (next->coder == NULL) {
+ // Allocate memory for the lzma_simple_coder structure if needed.
+ lzma_simple_coder *coder = next->coder;
+ if (coder == NULL) {
// Here we allocate space also for the temporary buffer. We
// need twice the size of unfiltered_max, because then it
// is always possible to filter at least unfiltered_max bytes
// more data in coder->buffer[] if it can be filled completely.
- next->coder = lzma_alloc(sizeof(lzma_coder)
+ coder = lzma_alloc(sizeof(lzma_simple_coder)
+ 2 * unfiltered_max, allocator);
- if (next->coder == NULL)
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &simple_code;
next->end = &simple_coder_end;
next->update = &simple_coder_update;
- next->coder->next = LZMA_NEXT_CODER_INIT;
- next->coder->filter = filter;
- next->coder->allocated = 2 * unfiltered_max;
+ coder->next = LZMA_NEXT_CODER_INIT;
+ coder->filter = filter;
+ coder->allocated = 2 * unfiltered_max;
// Allocate memory for filter-specific data structure.
if (simple_size > 0) {
- next->coder->simple = lzma_alloc(
- simple_size, allocator);
- if (next->coder->simple == NULL)
+ coder->simple = lzma_alloc(simple_size, allocator);
+ if (coder->simple == NULL)
return LZMA_MEM_ERROR;
} else {
- next->coder->simple = NULL;
+ coder->simple = NULL;
}
}
if (filters[0].options != NULL) {
const lzma_options_bcj *simple = filters[0].options;
- next->coder->now_pos = simple->start_offset;
- if (next->coder->now_pos & (alignment - 1))
+ coder->now_pos = simple->start_offset;
+ if (coder->now_pos & (alignment - 1))
return LZMA_OPTIONS_ERROR;
} else {
- next->coder->now_pos = 0;
+ coder->now_pos = 0;
}
// Reset variables.
- next->coder->is_encoder = is_encoder;
- next->coder->end_was_reached = false;
- next->coder->pos = 0;
- next->coder->filtered = 0;
- next->coder->size = 0;
-
- return lzma_next_filter_init(
- &next->coder->next, allocator, filters + 1);
+ coder->is_encoder = is_encoder;
+ coder->end_was_reached = false;
+ coder->pos = 0;
+ coder->filtered = 0;
+ coder->size = 0;
+
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_coder.h b/Utilities/cmliblzma/liblzma/simple/simple_coder.h
index 0952fad33..19c2ee03a 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_coder.h
+++ b/Utilities/cmliblzma/liblzma/simple/simple_coder.h
@@ -17,44 +17,56 @@
extern lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_ia64_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_ia64_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_arm_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_sparc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_sparc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
#endif
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_decoder.c b/Utilities/cmliblzma/liblzma/simple/simple_decoder.c
index 034e158ff..1d864f2bf 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_decoder.c
+++ b/Utilities/cmliblzma/liblzma/simple/simple_decoder.c
@@ -14,18 +14,17 @@
extern lzma_ret
-lzma_simple_props_decode(void **options, lzma_allocator *allocator,
+lzma_simple_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_bcj *opt;
-
if (props_size == 0)
return LZMA_OK;
if (props_size != 4)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_bcj), allocator);
+ lzma_options_bcj *opt = lzma_alloc(
+ sizeof(lzma_options_bcj), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_decoder.h b/Utilities/cmliblzma/liblzma/simple/simple_decoder.h
index b8bf590f7..bed8d37a9 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_decoder.h
+++ b/Utilities/cmliblzma/liblzma/simple/simple_decoder.h
@@ -16,7 +16,7 @@
#include "simple_coder.h"
extern lzma_ret lzma_simple_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_private.h b/Utilities/cmliblzma/liblzma/simple/simple_private.h
index fcf9f7c19..9d2c0fdd7 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_private.h
+++ b/Utilities/cmliblzma/liblzma/simple/simple_private.h
@@ -16,9 +16,7 @@
#include "simple_coder.h"
-typedef struct lzma_simple_s lzma_simple;
-
-struct lzma_coder_s {
+typedef struct {
/// Next filter in the chain
lzma_next_coder next;
@@ -33,12 +31,12 @@ struct lzma_coder_s {
/// Pointer to filter-specific function, which does
/// the actual filtering.
- size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+ size_t (*filter)(void *simple, uint32_t now_pos,
bool is_encoder, uint8_t *buffer, size_t size);
/// Pointer to filter-specific data, or NULL if filter doesn't need
/// any extra data.
- lzma_simple *simple;
+ void *simple;
/// The lowest 32 bits of the current position in the data. Most
/// filters need this to do conversions between absolute and relative
@@ -62,12 +60,13 @@ struct lzma_coder_s {
/// Temporary buffer
uint8_t buffer[];
-};
+} lzma_simple_coder;
extern lzma_ret lzma_simple_coder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters,
- size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters,
+ size_t (*filter)(void *simple, uint32_t now_pos,
bool is_encoder, uint8_t *buffer, size_t size),
size_t simple_size, size_t unfiltered_max,
uint32_t alignment, bool is_encoder);
diff --git a/Utilities/cmliblzma/liblzma/simple/sparc.c b/Utilities/cmliblzma/liblzma/simple/sparc.c
index 0ddd2ac9d..74b2655f3 100644
--- a/Utilities/cmliblzma/liblzma/simple/sparc.c
+++ b/Utilities/cmliblzma/liblzma/simple/sparc.c
@@ -15,7 +15,7 @@
static size_t
-sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
+sparc_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
@@ -26,8 +26,6 @@ sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
|| (buffer[i] == 0x7F
&& (buffer[i + 1] & 0xC0) == 0xC0)) {
- uint32_t dest;
-
uint32_t src = ((uint32_t)buffer[i + 0] << 24)
| ((uint32_t)buffer[i + 1] << 16)
| ((uint32_t)buffer[i + 2] << 8)
@@ -35,6 +33,7 @@ sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
src <<= 2;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + src;
else
@@ -58,7 +57,7 @@ sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
static lzma_ret
-sparc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+sparc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
@@ -68,7 +67,8 @@ sparc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
lzma_simple_sparc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return sparc_coder_init(next, allocator, filters, true);
}
@@ -76,7 +76,8 @@ lzma_simple_sparc_encoder_init(lzma_next_coder *next,
extern lzma_ret
lzma_simple_sparc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return sparc_coder_init(next, allocator, filters, false);
}
diff --git a/Utilities/cmliblzma/liblzma/simple/x86.c b/Utilities/cmliblzma/liblzma/simple/x86.c
index 95858e51e..23d0c4293 100644
--- a/Utilities/cmliblzma/liblzma/simple/x86.c
+++ b/Utilities/cmliblzma/liblzma/simple/x86.c
@@ -17,14 +17,14 @@
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
-struct lzma_simple_s {
+typedef struct {
uint32_t prev_mask;
uint32_t prev_pos;
-};
+} lzma_simple_x86;
static size_t
-x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
+x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
static const bool MASK_TO_ALLOWED_STATUS[8]
@@ -33,39 +33,34 @@ x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
static const uint32_t MASK_TO_BIT_NUMBER[8]
= { 0, 1, 2, 2, 3, 3, 3, 3 };
+ lzma_simple_x86 *simple = simple_ptr;
uint32_t prev_mask = simple->prev_mask;
uint32_t prev_pos = simple->prev_pos;
- size_t limit;
- size_t buffer_pos;
-
if (size < 5)
return 0;
if (now_pos - prev_pos > 5)
prev_pos = now_pos - 5;
- limit = size - 5;
- buffer_pos = 0;
+ const size_t limit = size - 5;
+ size_t buffer_pos = 0;
while (buffer_pos <= limit) {
- uint32_t offset;
- uint32_t i;
-
uint8_t b = buffer[buffer_pos];
if (b != 0xE8 && b != 0xE9) {
++buffer_pos;
continue;
}
- offset = now_pos + (uint32_t)(buffer_pos)
+ const uint32_t offset = now_pos + (uint32_t)(buffer_pos)
- prev_pos;
prev_pos = now_pos + (uint32_t)(buffer_pos);
if (offset > 5) {
prev_mask = 0;
} else {
- for (i = 0; i < offset; ++i) {
+ for (uint32_t i = 0; i < offset; ++i) {
prev_mask &= 0x77;
prev_mask <<= 1;
}
@@ -84,8 +79,6 @@ x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
uint32_t dest;
while (true) {
- uint32_t i;
-
if (is_encoder)
dest = src + (now_pos + (uint32_t)(
buffer_pos) + 5);
@@ -96,7 +89,8 @@ x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
if (prev_mask == 0)
break;
- i = MASK_TO_BIT_NUMBER[prev_mask >> 1];
+ const uint32_t i = MASK_TO_BIT_NUMBER[
+ prev_mask >> 1];
b = (uint8_t)(dest >> (24 - i * 8));
@@ -130,15 +124,17 @@ x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
static lzma_ret
-x86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters,
- &x86_code, sizeof(lzma_simple), 5, 1, is_encoder);
+ &x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder);
if (ret == LZMA_OK) {
- next->coder->simple->prev_mask = 0;
- next->coder->simple->prev_pos = (uint32_t)(-5);
+ lzma_simple_coder *coder = next->coder;
+ lzma_simple_x86 *simple = coder->simple;
+ simple->prev_mask = 0;
+ simple->prev_pos = (uint32_t)(-5);
}
return ret;
@@ -146,7 +142,8 @@ x86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
-lzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_x86_encoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return x86_coder_init(next, allocator, filters, true);
@@ -154,7 +151,8 @@ lzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern lzma_ret
-lzma_simple_x86_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_x86_decoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return x86_coder_init(next, allocator, filters, false);
diff --git a/Utilities/cmlibrhash/librhash/rhash.c b/Utilities/cmlibrhash/librhash/rhash.c
index ad6249b17..34e1eb305 100644
--- a/Utilities/cmlibrhash/librhash/rhash.c
+++ b/Utilities/cmlibrhash/librhash/rhash.c
@@ -18,6 +18,8 @@
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
+#include "ustd.h" /* Need this first within CMake. */
+
#include <string.h> /* memset() */
#include <stdlib.h> /* free() */
#include <stddef.h> /* ptrdiff_t */
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index ba1638eb0..a503041be 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -208,6 +208,22 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
)
endif()
+if(CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD")
+ list(APPEND uv_libraries
+ freebsd-glue
+ kvm
+ )
+ list(APPEND uv_headers
+ include/uv-bsd.h
+ )
+ list(APPEND uv_sources
+ src/unix/bsd-ifaddrs.c
+ src/unix/freebsd.c
+ src/unix/kqueue.c
+ src/unix/posix-hrtime.c
+ )
+endif()
+
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
list(APPEND uv_libraries
kvm